[M双指针] lc611. 有效三角形的个数(二分+双指针+线性扫描+算法优化)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M双指针] lc611. 有效三角形的个数(二分+双指针+线性扫描+算法优化)相关的知识,希望对你有一定的参考价值。
1. 题目来源
2. 题目解析
两种做法。体会二分和双指针的联系与区别。
方法一:排序+二分
- 先排序,然后枚举最小边
a
,次小边b
,最长边要满足a+b>c
,故要找到小于a+b
的最大的一个,二分找就行了。 - 二分时需要注意下边界问题,每次从
[b, n-1]
开始二分是正确的,找不到的话将停留在b
下标处,算答案的时候不会出错。 - 否则,遇见
[0, 0, 0]
这样的数据,从l=0, r=n-1
开始二分的话,会出错。 - 当然,当遇见边长为 0 的边,应该直接跳过,这样的话,
a+b
一定是>b
的,那么即便二分没找到答案,也会停留在小于a+b
的最大位置,也就是b
的位置。
- 时间复杂度: O ( n 2 l o g n ) O(n^2logn) O(n2logn)
- 空间复杂度: O ( n ) O(n) O(n)
方法二:双指针+线性扫描
- 转变一下枚举顺序,先枚举最大边
a
,再枚举次大边b
,次大边从a-1
开始向前枚举,b
呈递减趋势。最小边c
从 0 开始向b
枚举,成递增趋势。 - 那么,只要满足
c+b>a
即可。 b
越来越小,c
要越来越大,所以满足双指针的特性。- 并且
c
会递增枚举,和b
一样,最多只会枚举n
次,故总的时间复杂度是 O ( n 2 ) O(n^2) O(n2) 的。 - 额外注意下双指针的时间复杂度计算。
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( 1 ) O(1) O(1)
代码:
方法一:排序+二分
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = 0;
for (int a = 0; a < nums.size(); a ++ )
if (nums[a] > 0) { // 判断边长不为 0
for (int b = a + 1; b < nums.size(); b ++ ) {
int s = nums[a] + nums[b];
int l = 0, r = nums.size() - 1; // 可以从 0 开始
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] < s) l = mid;
else r = mid - 1;
}
res += r - b;
}
}
return res;
}
};
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = 0;
for (int a = 0; a < nums.size(); a ++ )
for (int b = a + 1; b < nums.size(); b ++ ) {
int s = nums[a] + nums[b];
// 注意这个细节,令左区间二分起点为b,不要从0开始,避免[0,0,0]这样的样例
int l = b, r = nums.size() - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] < s) l = mid;
else r = mid - 1;
}
res += r - b;
}
return res;
}
};
方法二:双指针+线性扫描
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = 0;
for (int a = 0; a < nums.size(); a ++ )
for (int b = a - 1, c = 0; b > 0 && c < b; b -- ) {
while (c < b && nums[c] + nums[b] <= nums[a]) c ++ ;
res += b - c; // c停下位置是第一个合法位置,相遇为0,相邻为1,故为b-c
}
return res;
}
};
以上是关于[M双指针] lc611. 有效三角形的个数(二分+双指针+线性扫描+算法优化)的主要内容,如果未能解决你的问题,请参考以下文章