滑动窗口系列总结

ACWING154 滑动窗口

(https://www.acwing.com/problem/content/156/)

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6+10;
int n,m;
int p[N],q[N];
int hh = 0,tt = -1;
int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 0; i < n; i ++ ){
        scanf("%d", &p[i]);
    }
    for(int i = 0; i < n; i++){
        if(hh <= tt && i-m+1 > q[hh]){
            hh++;
        }
        while(hh <= tt && p[q[tt]] >= p[i]){
            tt--;
        }
        q[++tt] = i;
        if(i+1>=m){
            printf("%d ",p[q[hh]]);
        }
    }
    cout  <<endl;
    hh = 0;
    tt = -1;
    for(int i = 0; i < n; i++){
        if(hh <= tt && i-m+1 > q[hh]){
            hh++;
        }
        while(hh <= tt && p[q[tt]] <= p[i]){
            tt--;
        }
        q[++tt] = i;
        if(i+1>=m){
            printf("%d ",p[q[hh]]);
        }
    }
    return 0;
    
}

ACW135 最大子序和

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 300005;
int q[N],a[N];
LL s[N];


int n,m;
int main(){
    cin >> n >> m;

    for(int i = 1; i <= n; i++){
        cin >> a[i];
        s[i] += s[i-1] + a[i];
    }
    int hh = 0, tt = 0;
    LL ans = INT_MIN;
    //q[0] = 0 这里放了一个s[0],我们要求的就是在j固定的前提下求在j-m到j中最小的值,可以用单调队列
    //这里的q中存的是下标
    for(int i = 1; i <= n; i++){
        while(hh <= tt && i - m > q[hh]){
            hh ++;
        }
        ans = max(ans,s[i] - s[q[hh]]);
        //从队头到队尾是一个递增序列,队头最小
        while(hh <= tt && s[q[tt]] >= s[i]){
            tt--;
        }

        q[++tt] = i;
    }
    //我写过i-1,i-1它是从零开始存的,存完再开始计算都是一样的。
    cout << ans << endl;
}

作者:acw_zzd
链接:https://www.acwing.com/activity/content/code/content/1776612/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

替换后的最长重复字符

(https://leetcode-cn.com/problems/longest-repeating-character-replacement/)

class Solution {
public:
    int characterReplacement(string s, int k) {
        int ans = 0;
        for(int i = 0; i < 26;i++){
            char c = (char)('A'+i);
            for(int i = 0, j = 0, cnt = 0; i < s.length(); i++){
                if(s[i] == c){
                    cnt++;
                }
                while(i-j+1-cnt > k){
                    if(s[j]==c){
                        cnt--;
                    }
                    j++;
                }
                ans = max(ans,i-j+1);
            }
        }
        return ans;
    }
};

和大于等于 target 的最短子数组

(https://leetcode-cn.com/problems/2VG8Kg/)

滑动窗口,用双指针实现:

窗口内之和小于目标值时右指针向右移动增加窗口宽度;
窗口内之和大于目标值时左指针向右移动减少窗口宽度。
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        if (nums.empty()) return 0;

        int left = 0;
        int curSum = 0;
        int minLength = INT_MAX;

        for (int right = 0; right < nums.size(); ++ right)
        {
            curSum += nums[right];
            while (left <= right && curSum >= target)
            {
                minLength = min(minLength, right - left + 1);
                curSum -= nums[left ++ ];
            }
        }

        return minLength == INT_MAX ? 0 : minLength;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值