有效三角形的个数
先上题目
这道题是比较经典的二分查找和双指针问题。主要思路是先对数组进行排序,因为我们要找的是组合问题,所以数组的排序对结果没有影响,但是排序后能加快我们寻找目标元素的速度。
排序+二分查找
算法流程:
- 对数组进行排序
- 固定两条边,利用二分法查找第三条边
- 二分法的边界长度就是固定两条边的条件下,满足第三条边的个数
- 每个固定两条边的组合,满足三角形条件基础下,更新三角形个数,res+=边界长度
- 固定边的组合走完
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int res = 0;
int n = nums.size();
//先进行排序 为二分查找建立条件
sort(nums.begin(),nums.end());
for(int i = 0; i < n - 2; ++i){
for(int j = i + 1; j < n - 1; ++j){
//固定两条边
int sum = nums[i]+nums[j];
//二分查找第三条符合得边 发现了二分查找的一个边界问题 right能否被取到是关键是<= 还是<
int left = j + 1;
int right = n - 1;
while(left <= right){
int mid = (right-left)/2 + left;
if(nums[mid] < sum){
left = mid + 1;
}else{
right = mid - 1 ;
}
}
//判断边界 如果右边界都满足那么左边界到右边界上的每一个元素都满足
if(nums[right]<sum){
res = res + right - j;
}
}
}
return res;
}
};
排序+双指针
算法流程:
- 数组排序
- 定义左边界和右边界,固定一条边,注意这里的边是数组最右边的元素,咱们倒序固定
- 当左边界比右边界小,判断?a[left]+a[right]>a[i]如果满足,那么right–,因为数组从左到右是升序,我减少右边界,相当于a[right]减小
- 反之,left++
- 维护的res+=right - left
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int n = nums.size();
int res = 0;
sort(nums.begin(),nums.end());
for(int i = n - 1; i > 1; --i){
int left = 0;
int right = i - 1;
while(left < right){
if(nums[left] + nums[right] > nums[i]&&nums[left]!=0&&nums[right]!=0&&nums[i]!=0){
res+=right-left;
--right;
}
else{
++left;
}
}
}
return res;
}
};
逆序双指针这思路确实顶