209.长度最小的子数组
子数组元素之和大于等于target
重点:滑动窗口
为什么用滑动窗口?子数组是连续的
一开始自己写的:
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int left=0;int right=0;int minlen=numeric_limits<int>::max();int sum=0;while(right<nums.size()){int len=right-left+1;if(sum==target){minlen=(len<minlen)?len:minlen;}else if(sum<target){sum+=nums[right++];}else{sum-=nums[left++];}}return minlen;}
};
但是时间超过限制了。问题在于这个循环条件 while(right<nums.size())
并不是每一次都更新的,所以相当于还是暴力解法。而且题目说的是大于等于target,而不是等于。
换一个方式来思考这个问题:暴力解法是两个for循环,一个是数组起始位置,一个是数组结束位置。现在要用一个for循环来解决问题,那么这个for循环应该是标记数组的结束位置,也就是窗口right。for循环内部则是用一个while来移动滑动窗口起始位置。
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int left=0;int minlen=INT32_MAX;int sum=0;for(int right=0;right<nums.size();right++){sum+=nums[right];while(sum>=target){int len=right-left+1;minlen=min(len,minlen);sum-=nums[left++]; // 减少一个元素看是否仍然符合条件,尝试更小值}}return minlen==INT32_MAX ? 0:minlen;}
};
59.螺旋矩阵II
没啥技巧,就是考验对转圈的控制能力
class Solution {
public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n,vector<int>(n,0));int loop=n/2; //要转几圈int start=0;int cnt=1;int offset=1; //这个自己没想到int i,j;while(loop--){i=start;j=start;//上边for(j; j<n-offset; j++){res[i][j]=cnt++;}//右边for(i; i<n-offset; i++){res[i][j]=cnt++;}//下边for(j; j>start; j--){ // 注意这个边界条件res[i][j]=cnt++;}//左边for(i; i>start; i--){res[i][j]=cnt++;}start++;offset++;}if(n%2){res[n/2][n/2]=n*n;}return res;}
};
设置 offset
变量是我一开始没想到的,用这个可以保证每转一圈就内推一格
区间和
核心思想:前缀和 presum [a,b]sum=p[b]-p[a-1]
#include <iostream>
#include <vector>
using namespace std;int main(){int n,a,b;cin >> n;int presum=0;vector<int> p(n);int cur;for(int i=0; i<n; i++){cin >> cur; // scanf("%d", &vec[i]);presum+=cur;p[i]=presum;}int sum;while(cin >> a >> b){ //while (~scanf("%d%d", &a, &b))if(a==0) sum=p[b];else sum=p[b]-p[a-1];cout << sum << endl;// printf("%d\n", sum);}return 0;}
C++ 代码 面对大量数据 读取 输出操作,最好用scanf 和 printf,耗时会小很多:
开发商购买土地
区间和的应用,分成了行区间和/列区间和
#include <iostream>
#include <vector>
#include <climits>
using namespace std;int main(){int n,m;cin>>n>>m;vector<int> sn(n,0);vector<int> sm(m,0);vector<vector<int>> nums(n, vector<int>(m)) ;int sum=0;for (int i=0; i<n; i++){for (int j=0; j<m; j++){cin>>nums[i][j];sum=sum+nums[i][j];sn[i]+=nums[i][j];//横前缀和(压缩列)sm[j]+=nums[i][j];//纵前缀和(压缩行)}}int minSum=INT_MAX;//横切int hengSum=0;for (int hengCnt=0; hengCnt<n-1; hengCnt++){hengSum+=sn[hengCnt];minSum=min(minSum,abs(sum-hengSum-hengSum));//abs((sum-hengSum)-hengSum) 是两半划分的差值}//纵切int shuSum=0;for (int shuCnt=0; shuCnt<m-1; shuCnt++){shuSum+=sm[shuCnt];minSum=min(minSum,abs(sum-shuSum-shuSum));}cout << minSum;return 0;
}