参考资料来源灵神在力扣所发的题单,仅供分享学习笔记和记录,无商业用途。
原理:在连续范围内进行数据维护,每次移动去头添尾。
应用场景:需要对连续区间进行操作(子数组、子串...)
模板:
for(int i=0;i<s.size();i++){
//数据插入(添尾)
if(i+1>=k){ //满足滑窗长度
//数据更新
if(当前滑窗第一位满足插入条件) //数据删除(去头)
}
}
力扣题单练习(灵神题单中摘取题目)
class Solution {
public:
int numOfSubarrays(vector<int>& arr, int k, int threshold) {
threshold*=k; //思维转换:换成子数组数据总和大于等于threshold
int ret=0,buff=0;
for(int i=0;i<arr.size();i++){
buff+=arr[i]; //插入数据
if(i+1>=k){ //满足滑窗长度
if(buff>=threshold) ret++; //更新结果
buff-=arr[i-k+1]; //删除数据
}
}
return ret;
}
};
class Solution {
public:
long long maxSum(vector<int>& nums, int m, int k) {
long long ret=0,buff=0;
unordered_map<int,int> map;
for(int i=0;i<nums.size();i++){
buff+=nums[i]; //插入数据
map[nums[i]]++; //记录滑窗中不同元素
if(i+1>=k){ //进入滑窗
if(map.size()>=m) ret=max(ret,buff); //更新结果
//对滑窗淘汰元素进行处理,因为元素头元素还跟滑窗内元素相同,不能直接删除,需要判断次数
if(map[nums[i-k+1]]==1) map.erase(nums[i-k+1]);
else map[nums[i-k+1]]--;
//淘汰原滑窗头部元素
buff-=nums[i-k+1];
}
}
return ret;
}
};
解法一:
剩下的元素+抽取元素=原数据,最小化剩下元素,就能获得最大点数。
剩下元素必须是连续的,采用滑窗进行更新数据
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int n=cardPoints.size()-k,ret=INT_MAX,buff=0;
//边界处理
if(k==0) return 0;
if(k==cardPoints.size()) return reduce(cardPoints.begin(),cardPoints.end());
for(int i=0;i<cardPoints.size();i++){
buff+=cardPoints[i]; //插入
if(i+1>=n){
ret=min(ret,buff); //更新
buff-=cardPoints[i-n+1]; //删除
}
}
return reduce(cardPoints.begin(),cardPoints.end())-ret;
}
};
解法二:
枚举选择头1~k元素加对应尾k-头选择元素进行组合,求出最大值
class Solution {
public:
int maxScore(vector<int>& cardPoints, int k) {
int ret=0;
vector<int> left(k+1,0),right(k+1,0);
left[0]=0;
right[0]=0;
for(int i=1;i<=k;i++) left[i]+=left[i-1]+cardPoints[i-1]; //前缀和
for(int j=cardPoints.size()-1,n=1;j>=0 && n<=k;j--,n++) right[n]+=right[n-1]+cardPoints[j]; //后缀和
for(int i=0;i<=k;i++) ret=max(ret,left[i]+right[k-i]); //组合枚举
return ret;
}
};
思路:minutes为窗口大小,枚举所有滑窗获得区间最大值+满足条件的元素和
class Solution {
public:
int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
int ret=INT_MIN,buff=0,ans=0;
for(int i=0;i<customers.size();i++){
if(grumpy[i]==0) ans+=customers[i];
}
//滑窗三部曲
for(int i=0;i<customers.size();i++){
if(grumpy[i]==1) buff+=customers[i];
if(i+1>=minutes){
ret=max(ret,buff);
if(grumpy[i-minutes+1]==1) buff-=customers[i-minutes+1];
}
}
return ret+ans;
}
};