Given an integer array nums
, return the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle.
Example 1:
Input: nums = [2,2,3,4] Output: 3 Explanation: Valid combinations are: 2,3,4 (using the first 2) 2,3,4 (using the second 2) 2,2,3
Example 2:
Input: nums = [4,2,3,4] Output: 4
Constraints:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
这道题给了一个数组,问你数组里随便挑三个数字,能形成一个三角形的组合有多少种。一看就知道又是有点算法技巧的,但是我不会。看了答案,说是类似于3sum的思想,就回去复习了3sum,果然3sum也忘了。好不容易复习完3sum,回到这道题,还是有点被卡住。在3sum的sort + 2 pointers的基础之上,这道题主要的技巧在于,我们在外层for loop的时候最好是从高往低loop,这样的话我们相当于固定了三角形的最长边,这样只要剩下两条边加起来的长度能大于这条最大的边的话就成功了。比如我们固定了k,现在内层是low和high,只要low + high > k,那么在low和high之间我不管怎么往上移动low,这些都一定是valid的组合,就可以result += (high - low)。反之,我们就需要往上移动low,找到最小的符合条件的low了。另外还需要注意的是,在上面能加result的情况下,我们还可以接着往下移动high,看看能不能凑出更小的,这点也是我刚开始没想到的。所以其实这里相当于是先固定最长边,再固定第二长边,来找最短边的最小值。这个帖子的例子很形象生动:https://leetcode.com/problems/valid-triangle-number/solutions/128135/a-similar-o-n-2-solution-to-3-sum
代码没啥坑,主要就是上面提到的++ --搞清楚就行了:
class Solution {
public int triangleNumber(int[] nums) {
int result = 0;
Arrays.sort(nums);
for (int i = nums.length - 1; i >= 0; i--) {
int low = 0;
int high = i - 1;
while (low < high) {
if (nums[low] + nums[high] > nums[i]) {
result += high - low;
high--;
} else {
low++;
}
}
}
return result;
}
}