Problem: 611. 有效三角形的个数
首先我们来分析一下本题的思路
三角形两边之和大于第三边则可以构成三角形
其实对于三角形的判断我们无需去判别三次,而是可以进行取巧
a + b > c
即可,而对于a + c > b
与b + c > a
则不用去进行一个比较,因为此时[c]
已经是最大的了,那再去加上a
或者b
的话一定会更大,所以无需去做比较然后我们根据上面的思路来分析一下本题的算法原理
for(int i = 0;i < n; ++i)
{
for(int j = i + 1;j < n; ++j)
{
for(int k = j + 1;k < n; ++k)
{
check(nums[i], nums[j], nums[k]);
}
}
}
我们可以来看一下运行后的结果
再来试着分析一下复杂度:
check()
函数而言,如果我们还是使用上面判断三次的方式来看三条边是否可以构成三角形,那么最终因为外层的循环就会使得时间复杂度到达 3 O ( n 3 ) 3O(n^3) 3O(n3);接下去我就来介绍一下【双指针】这种解法
[c]
;然后呢我们拿左指针left
从左向右进行遍历,拿右指针right
从右往左开始遍历a + b = 11 > c
,那么就可以利用我们上面所介绍的这种思想,无需再去多判断2 + 9
、3 + 9
、4 + 9
等等这些都是要比10
要来得大的,那其实我们根本无需再去判断这些数据,从【2】~【5】这5组数据均可以组成三角形,那此时如果我们要得到这个5的话只需要让right - left
即可right--
进行下一个数据的判断即可2 + 5 = 7 < 10
,那么此时我们可以继续去观察从【2】~【5】的这一堆数,它们一定是比5
来得小的,那我们也无需再去多做比较了,对于这个【2】来说我们就可以舍弃了所以我们在来总结一下上面这种解法
来说一下双指针这种解法的时间复杂度, 首先的话我们要在N个数内找到那个最大的数,然后的话还要使用【双指针】去遍历从
0 ~ n - 1
这N - 1个数,那么时间复杂度即为 O ( N 2 ) O(N^2) O(N2)
对于空间复杂度来说,没有去开辟任何的空间,所以为 O ( 1 ) O(1) O(1)
来展示一下最终的代码
class Solution {
public:
int triangleNumber(vector<int>& nums) {
// 1.优化
sort(nums.begin(), nums.end());
// 2.利用双指针解决问题
int ret = 0, n = nums.size();
for(int i = n - 1; i >= 2; --i) // 先固定最大的数
{
// a : nums[left]
// b : nums[right]
// c : nums[i]
int left = 0, right = i - 1;
while(left < right)
{
if(nums[left] + nums[right] > nums[i])
{
ret += right - left;
right--;
}
else
{
left++;
}
}
}
return ret;
}
};