209.长度最小的子数组
代码随想录链接:代码随想录 (programmercarl.com)
1. 暴力
两个for循环遍历,一开始读错题看成等于了,没看到大于等于。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum=0;
int minlength=100001;//题目给的数组最长是100000
for(int i=0;i<nums.size();i++){
sum=0;
for(int j=i;j<nums.size();j++){
sum+=nums[j];
if(sum>=target){
minlength=min(minlength,j-i+1);
}
}
}
if(minlength==100001){
return 0;
}
else{
return minlength;
}
}
};
2.滑动窗口
考虑的问题:
窗口里面是什么?窗口起始位置什么时候滑?终止位置什么时候滑?
窗口里面是符合条件的子数组,起始位置在子数组>=target的时候向后移动,终止位置在子数组<target的时候移动。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int begin=0;
int minlength=100001;
int sum=0;
for(int j=0;j<nums.size();j++){
sum+=nums[j];
while(sum>=target){
minlength=min(minlength,j-begin+1);
sum-=nums[begin];
begin++;
}
}
if(minlength==100001){
return 0;
}
else{
return minlength;
}
}
};
59.螺旋矩阵
代码随想录链接:代码随想录 (programmercarl.com)
循环不变量,填矩阵时候边角元素的处理。左闭右开。变量的变化。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> result(n,vector<int>(n,0));
int startx=0;
int starty=0;
int num=1;
int offset=1;
for(int loop=0;loop<n/2;loop++){
int i=startx;
int j=starty;
for(j;j<n-offset;j++){//左闭右开
result[i][j]=num;
num++;
}
for(i;i<n-offset;i++){
result[i][j]=num;
num++;
}
for(j;j>starty;j--){
result[i][j]=num;
num++;
}
for(i;i>startx;i--){
result[i][j]=num;
num++;
}
startx++;
starty++;
offset+=1;
}
if(n%2==1){
result[n/2][n/2]=n*n;
}
return result;
}
};
区间和
代码随想录链接:58. 区间和 | 代码随想录 (programmercarl.com)
前缀和在涉及计算区间和的问题时非常有用,计算时注意区间
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> nums(n,0);
vector<int> p(n,0);
int sum=0;
for(int i=0;i<n;i++){
cin>>nums[i];
sum+=nums[i];
p[i]=sum;
}
int a,b;
while(cin>>a>>b){
cout<<p[b]-p[a-1]<<endl;
}
}
开发商购买土地
使用前缀和来写就可以很快的计算差值
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
int sum=0;
vector<vector<int>> land(n,vector<int>(m,0));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>land[i][j];
sum+=land[i][j];
}
}
//统计横向
vector<int> hori(n);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
hori[i]+=land[i][j];
}
}
//统计纵向
vector<int> vert(m);
for(int j=0;j<m;j++){
for(int i=0;i<n;i++){
vert[j]+=land[i][j];
}
}
int result=90001;
int horicut=0;
for(int i=0;i<n;i++){
horicut+=hori[i];
result=min(result,abs(sum-horicut-horicut));
}
int vertcut=0;
for(int i=0;i<m;i++){
vertcut+=vert[i];
result=min(result,abs(sum-vertcut-vertcut));
}
cout << result << endl;
}
总结
学习了滑动窗口,加深对二分查找时提到的循环不变量的理解,学习了前缀和。
今天的题感觉都是看了题解之后能写出来,但是有些没有底气,好像就是死记硬背过去了一样,可能还需要进一步巩固。用时大概3小时
数组部分的最后一天,主要需要掌握的:二分、双指针(快慢、头尾)、滑动窗口、模拟行为、前缀和。