滑动窗口
模式:一层for循环,里面一个while
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int result = INT_MAX;
int i = 0;
int sum = 0;
for(int j = 0;j< nums.size();j++){
sum += nums[j];
while(i<=j && sum >= target){
int dis = j - i + 1;
result = min(result, dis);
sum -= nums[i];
i++;
}
}
return result == INT_MAX ? 0 : result;
}
};
前缀和
一维前缀和
计算数组start到end的和,可以采用前缀和简化计算:
s
t
a
r
t
>
0
:
s
u
m
[
s
t
a
r
t
:
e
n
d
]
=
s
u
m
[
0
,
e
n
d
]
−
s
u
m
[
0
,
s
t
a
r
t
−
1
]
s
t
a
r
t
=
0
:
s
u
m
[
s
t
a
r
t
:
e
n
d
]
=
s
u
m
[
0.
e
n
d
]
start > 0:sum[start:end] = sum[0,end] - sum[0,start-1] \\ \\start=0:sum[start:end]= sum[0.end]
start>0:sum[start:end]=sum[0,end]−sum[0,start−1]start=0:sum[start:end]=sum[0.end]
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> r(n);
int count = n;
int i=0;
int sum = 0;
vector<int> p(n);
while(count--){
cin>>r[i];
sum += r[i];
p[i] = sum;
i++;
}
int start;int end;
while(cin>>start>>end){
if(start == 0) cout<<p[end] << endl;
else cout<<p[end] - p[start - 1]<<endl;
}
}
二维前缀和
分析:前缀和表示为前一块土地的面积A,另一块面积为B,总和面积S,面积差为:
∣
B
−
A
∣
=
∣
S
−
A
−
A
∣
=
∣
S
−
2
A
∣
|B - A| = |S - A - A| = |S - 2A|
∣B−A∣=∣S−A−A∣=∣S−2A∣
由于只能横着或者竖着分,所以必须在遍历到行末尾或者列末尾的时候计算面积差
#include<iostream>
#include<vector>
#include<climits>
using namespace std;
int main(){
int n;int m;
cin>>n>>m;
vector<vector<int>> r(n, vector<int>(m));
int sum = 0;
// sum 记作前缀和
for(int k =0;k<n;k++){
for(int i = 0;i<m;i++){
cin>>r[k][i];
sum += r[k][i];
}
}
int result = INT_MAX;
int count = 0;
for(int i = 0;i<n;i++){
for(int j =0;j<m;j++){
count += r[i][j];
if(j == m-1) result = min(result, abs((sum - count) - count));
}
}
count = 0;
for(int j = 0;j<m;j++){
for(int i =0;i<n;i++){
count += r[i][j];
if(i== n-1) result = min(result, abs((sum - count) - count));
}
}
cout<<result<<endl;
}
螺旋矩阵
注意区分奇数偶数,如果是n为奇数的话,需要单独给矩阵最中间的位置赋值
循环处理:左闭右开
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n));
int count = 1;
int sum = n*n;
int startx = 0; int starty = 0;
int i =0; int j = 0;
int offset = 1;
int loop = n/2;
while(loop--){
i = startx;
j = starty;
// 下面开始的四个for就是模拟转了一圈
// 模拟填充上行从左到右(左闭右开)
for (j; j < n - offset; j++) {
res[i][j] = count++;
}
// 模拟填充右列从上到下(左闭右开)
for (i; i < n - offset; i++) {
res[i][j] = count++;
}
// 模拟填充下行从右到左(左闭右开)
for (; j > starty; j--) {
res[i][j] = count++;
}
// 模拟填充左列从下到上(左闭右开)
for (; i > startx; i--) {
res[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 1;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2) {
res[n/2][n/2] = count;
}
return res;
}
};