611. Valid Triangle Number
1 | class Solution { |
构造三角形就是两边之和大于第三边.
我的想法就是先sort一下. 然后模仿3sum那样用两个pointer. 但是我是从左到右遍历. 因此比如第0个元素为一边, 从1到n - 1的元素开始two pointers遍历. 如果nums[i] + nums[left] > nums[right], 这就说明left到right间的元素和nums[i]配对都会大于nums[right], 此时我们可以在ans中加上. 但是如果nums[i] + nums[left] <= nums[right], 可能有些元素在right左侧能和i, left构成三角形. 于是我们要不移动left, 移动right, 到某个位置后, 我们发现可以于是在ans中添加个数. 此时我们就要让left再 + 1. 但这里的问题就是, right也要重置到最右端, 因为在此时right右侧可能有的元素可以和现在的nums[i], nums[left]组成三角形了, 毕竟left左移了.
因此这样做的问题就是一旦left左移, right就要重置到最右端.
但是网友就是牛逼, 我们倒着遍历即可. 也就是我们先确定最大边是多少. 然后维护两个pointers, 左一个, 右一个. 如果nums[left] + nums[right] <= nums[big]. 我们需要移动left. 如果nums[left] + nums[right] > nums[big], 这说明从right到left间的数字都可以和right配对大于big, 此时ans加上这些对儿即可. 此时我们知道right作为第二大边的情况没有了. 我们移动right. 那此时需要移动left吗? 答案是不需要, 因为此时最左边到left这里和right配对都小于big, 更何况此时right还移动了一格. 因此我们知道right更新后, left左侧的位置都不满足, 至于left满不满足不一定了, 我们当然也没有移动left.
等于思路是先确定一个big, 再确定一个second big. 然后left就移动, 移动到某个位置满足题意, 把答案加到ans上, 移动second big一位, 然后继续移动left, 判断..这个过程.
时间复杂度: O(n^2)
空间复杂度: O(1)