题目
给定一个包含非负整数的数组 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
思路
题目判断三角形,首先我们需要回顾一个小学知识点,三角形的两边和是要大于第三边的,所以按常理讲拿到三个数后需要来回判断三次,而直接暴力枚举的话,会大大增加时间复杂度,这里首先就可以做一个优化,先把三个数从小到大排,这样只用判断一次即可。
暴力枚举三次for循环来依次遍历,复杂度为n^3。明显不可取。
通过上述小小优化可以先对数组进行一次排序,让其先变的有序,有序后更方便进行枚举。
此时可以利用双指针(这里是三指针)通过单调性来对数据进行遍历。
上图为例,先固定出一个最大的数作为c,然后让其他数依次组合来进行遍历,最左为a最右为b,满足的情况和为sum。
初步判断a+b>c,所以符合条件,同时可以得出a往右到b之间所有的数相加都满足此条件,b直接--左移。sum+=b-a。
此时right指向的数为5,此时判断a+b<c,此时也可以得出a往右到b之间所有的数相加都不满足此条件,因为此时b是这个区间中的最大数,b都不满足,比b小的自然也不满足,left++向右移动一位。
然后依次重复此过程,直到left和right相遇,此时c为10的情况就遍历完成,然后c--,a b分别重置。
题解
class Solution {
public:int triangleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());int a=0,b=nums.size()-2,c=nums.size()-1;int sum=0;while(c>=2){while(a<b){if(nums[a]+nums[b]>nums[c]){sum+=(b-a);--b;}else{++a;}}--c;a=0;b=c-1;}return sum;}
};