剑指 Offer 和大于等于 target 的最短子数组
今天主要学习的是滑动窗口就用滑动窗口方法做,首先很多人不知道什么是滑动窗口,滑动窗口看成如下图一样数组框的一部分在这个区间里面找合适的结果。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int ans=INT_MAX,sum=0;
int s=0,e=0;//定义左区间和右区间
while(e<nums.size()){
sum+=nums[e];
while(sum>=target){//当和大于等于target则说明要求该区间的和可能满足
ans=min(e-s+1,ans);//找最小的区间长度
sum-=nums[s];
s++;
}
e++;
}
return ans==INT_MAX?0:ans;//若ans的值未变化则说明没找到否则找到最短的
}
};
剑指 Offer II 和为s的连续正数序列
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
int l=1,r=1;//定义左边界,和右边界
int sum=1;//让区间左闭右闭
vector<vector<int>>ans;
while(l<=target/2){//因为序列中至少包含两个数字所以左区间可以到target/2
if(target>sum){//target比sum大则让右区间动起来
r++; //因为开始没考虑r所以要先加r
sum+=r;
}
else if(target<sum){//target比sum小则让左区间动起来
sum-=l;
l++;
}
else{
vector<int>a;
for(int k=l;k<=r;k++){//左闭右闭区间复制
a.push_back(k);
}
ans.push_back(a);
sum-=l;
l++;
}
}
return ans;
}
};
滑动窗口的最大值
#include <vector>
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
vector<int>ret;
deque<int>a;//用双端队列来维护最大值
if(num.size()==0||size==0)
return {};//判特殊情况
for(int i=0;i<num.size();i++){
while(!a.empty()&&num[a.back()]<num[i]){//如果比队列最后一个值大则删除最后的元素
a.pop_back();
}
a.push_back(i);//插入当前最大值的下标
if(a.front()+size<=i){//若旧下标失效
a.pop_front();//则头删
}
if(i+1>=size){//判断是否形成窗口
ret.push_back(num[a.front()]);
}
}
return ret;
}
};