时间复杂度
O(n): 左右标记都最多移动 n 次
连续子区间和
窗口内的元素之和,大于给定值时,则窗口右标及之后的子数组都应该算在结果中
不能统计左下标及之前的个数,因为窗口之和可能远大于给定值,之后向后滑动时,会重复统计:
数组: 2 4 7 和:6
[2, 2] -> 0
[2, 4] -> 1
[4, 4] -> 0
[4, 7] -> 2
[7,7] -> 3
有重复统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| #include <vector>
#include <iostream>
using namespace std;
long long f(vector<int> &v, long long sum) {
if(v.size() == 0) {
return 0;
}
long long res = 0;
int l = 0;
int r = 0;
long long s = v[0];
while(l < v.size()) {
if(s < sum) {
if(r + 1 >= v.size()) {
break;
}
r++;
s += v[r];
continue;
}
if(s >= sum) {
res += v.size() - r;
s -= v[l];
l++;
}
}
return res;
}
int main() {
int c;
int x;
cin >> c >> x;
vector<int> v;
for(int i = 0; i < c; i++) {
int k;
cin >> k;
v.push_back(k);
}
cout << f(v, x) << endl;
return 0;
}
|
3Sum
排序后,求两数之和等于相反值。
窗口:如果两数之和大于相反值,窗口减少,否则窗口增加
时间复杂度:O(n^2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
sort(nums.begin(), nums.end());
vector<vector<int>> res;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) {
break;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int m = i + 1;
int n = nums.size() - 1;
while (m < n) {
if (nums[m] + nums[n] == -nums[i]) {
res.push_back(vector<int> { nums[i], nums[m], nums[n] });
m++;
n--;
while (m < n && nums[m] == nums[m - 1]) {
m++;
}
while (n > m && nums[n] == nums[n + 1]) {
n--;
}
} else if (nums[m] + nums[n] < -nums[i]) {
m++;
while (m < n && nums[m] == nums[m - 1]) {
m++;
}
} else {
n--;
while (n > m && nums[n] == nums[n + 1]) {
n--;
}
}
}
}
return res;
}
};
|
Contains Duplicate III
桶排序,巧妙之处在于一个捅中只会用一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(k <= 0 || t < 0) {
return false;
}
long long tt = t;
map<long long, long long> buckts;
long long min_num = *max_element(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++) {
if(i > k) {
int p = i - k - 1;
long long b = (nums[p] - min_num) / (tt + 1);
buckts.erase(b);
}
long long b = (nums[i] - min_num) / (tt + 1);
if(buckts.find(b - 1) != buckts.end()) {
if(nums[i] - buckts[b - 1] <= tt) {
return true;
}
}
if(buckts.find(b + 1) != buckts.end()) {
if(buckts[b + 1] - nums[i] <= tt) {
return true;
}
}
if(buckts.find(b) != buckts.end()) {
return true;
}
buckts[b] = nums[i];
}
return false;
}
}
|