题目
给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。
示例 1:
输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
示例 2:
输入: nums = [4,2,3,4]
输出: 4
提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
题解
排序+二分查找
三角形要满足a+b>c; a+c>b; b+c>a
当排序好之后, a+c>b和b+c>a一定满足, 只需寻找a+b>c
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int len = nums.size();
if(len<3)
return 0;
sort(nums.begin(),nums.end());
int result = 0;
for(int i=0;i<len-2;i++)
{
for(int j=i+1;j<len-1;j++)
{
int left = j+1;
int right = len-1;
int target = nums[i]+nums[j];
while(left<=right)
{
int mid = (left+right)>>1;
if(nums[mid]<target)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
result+= right-j ;
}
}
return result;
}
};
排序+双指针
属于暴力的优化
暴力方法是三个循环, 每次都重置k并循环
但是在排序好的序列中, 因为是递增的, 所以a+b也是递增的, 也就是说对于每个来说, 不需要每次都重置k进行遍历, 只需要接着上一次的继续往后走就行了
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int len = nums.size();
if(len<3)
return 0;
sort(nums.begin(),nums.end());
int result = 0;
for(int i=0;i<len-2;i++)
{
int k = i+1;
for(int j=i+1;j<len-1;j++)
{
int target = nums[i] + nums[j];
while(k+1<len && nums[k+1]<target)
k++;
result += max(k-j,0);
}
}
return result;
}
};