题目解析
算法讲解
回顾知识:任意两数之和大于第三数就可以构成三角形
算法 1:暴力枚举
c
int triangleNumber(vector<int>& nums)
{
// 1. 排序
sort(nums.begin(), nums.end());
int n = nums.size(), ret = 0;
// 2. 从⼩到⼤枚举所有的三元组
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
for (int k = j + 1; k < n; k++)
{
// 当最⼩的两个边之和⼤于第三边的时候,统计答案
if (nums[i] + nums[j] > nums[k])
ret++;
}
}
}
return ret;
}
我们通过枚举每三个没有使用的数字,但是这样加上sort
函数的时间,时间复杂度太高
算法 2:双指针
我们先确定一个最大数,然后在这个最大数的左边的区间寻找有效三角形
- 如果现在的左右指针的值加起来已经 > 每一次确定的最大值:那么现在的left指针已经不需要移动了,因为当前这个数组已经是经过排序的了,所以当前的left满足条件,left右边的数字也满足条件,此时[left, right]区间的有效三角形的个数就是right - left
- 如果现在左右指针的值讲起来 <= 每一次确定的最大值:那么就需要将left++,在新的[left, right]区间中寻找有效三角形个数,left++的道理同上述
代码编写
cpp
class Solution {
public:
int triangleNumber(vector<int>& nums) {
//先排序
sort(nums.begin(), nums.end());
//两数之和 > 第三数
int ret = 0;
int n = nums.size();
for(int i = n - 1; i >= 2; i--)
{
int left = 0;
int right = i - 1;
//现在nums[i] 就是最大的值,在最大值左边的有序区间里面寻找有效三角形
while(left < right)
{
if(nums[left] + nums[right] > nums[i])
{
ret += (right - left);
right--;
}
else left++;
}
}
return ret;
}
};