文章目录
- 一、题目
- 二、算法讲解
- 三、题目链接
- 四、补充
一、题目
给定一个包含非负整数的数组 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: 暴力枚举,三层循环,得到一个三角形的三条边,然后判断是否为三角形,但是时间复杂度为O(n3),可能会超时。
思路2: 可以通过双指针来模拟三层循环的过程,通过一些条件来规避三层循环。
- 首先对数据进行升序排序
- 将最后也就是最大的数设置为第三条边。
- 两个指针left和right分别指向数据开头和最大数的前一个位置
- 进行判断:
如果left和right的和大于最大的数,那么固定right,left++,两数之和都大于最大的数,因为该组数据是升序,这时候就相当于把right这个位置的数的每种可能都遍历了一遍,只要right-left计算一下三角形个数加到一起就行了,之后right–;
如果left和right的和小于最大的数,那么固定left,right–,每种情况都是小于最大的数的,这时候就相当于把left这个位置的数的每种可能都遍历了一遍,由于这种情况是不满足三角形的,只需要left++就行了。 - 最大的数位置-1,回到步骤3再次进行判断,直到最大数的位置到2(因为从0开始,0、1位置肯定不可能作为三角形最大的边)。
代码:
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,right=i-1;while(left<right){if((nums[left]+nums[right])>nums[i]){ret+=(right-left);right--;}else{left++;}}}return ret;}
};
三、题目链接
611. 有效三角形的个数
四、补充
类似的题目还有
11. 盛最多水的容器