Leetcode滑动窗口

滑动窗口模板

/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    unordered_map<charint> need, window;
    for (char c : t) need[c]++;
    
    int left = 0, right = 0;
    int valid = 0
    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s[right];
        // 增大窗口
        right++;
        // 进行窗口内数据的一系列更新
        ...

        /*** debug 输出的位置 ***/
        printf("window: [%d, %d)\n", left, right);
        /********************/
        
        // 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s[left];
            // 缩小窗口
            left++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}

其中两处 ... 表示的更新窗口数据的地方,到时候你直接往里面填就行了。

1052. 爱生气的书店老板

问题描述:

有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。

在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。

当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。

书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。

请你返回 这一天营业下来,最多有多少客户能够感到满意 。
 

示例 1:

输入:customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], minutes = 3
输出:16
解释:书店老板在最后 3 分钟保持冷静。
感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.

代码:

class Solution {
public:
    int maxSatisfied(vector<int> &customers, vector<int> &grumpy, int minutes) {
        int length = customers.size();
        int total = 0;
        for (int i = 0; i < length; i++) {
            if (grumpy[i] == 0) {
                total += customers[i];
            }
        }
        return slidingWindow(customers, grumpy, minutes, total);
    }

    /* 滑动窗口算法框架 */
    int slidingWindow(vector<int> &customers, vector<int> &grumpy, int minutes, int total) {
        int res = 0;
        int tmp = total;
        int left = 0, right = 0;
        while (right < customers.size()) {
            // c 是将移入窗口的字符
            int c = customers[right];
            if (grumpy[right] == 1) {
                tmp += c;
            }

            // 判断左侧窗口是否要收缩
            while (right - left + 1 == minutes) {
                // d 是将移出窗口的字符
                int d = customers[left];
                // 进行窗口内数据的一系列更新
                res = max(res, tmp);
                if (grumpy[left] == 1) {
                    tmp -= d;
                }
                // 缩小窗口
                left++;
            }
            // 增大窗口
            right++;
        }
        return res;
    }
};

76. 最小覆盖子串

题目:

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

代码:

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<charint> need, window;
        for (char c: t) need[c]++;

        int left = 0, right = 0;
        int valid = 0;
        // 记录最小覆盖子串的起始索引及长度
        int start = 0, len = INT_MAX;
        while (right < s.size()) {
            // c 是将移入窗口的字符
            char c = s[right];
            // 扩大窗口
            right++;
            // 进行窗口内数据的一系列更新
            if (need.count(c)) {
                window[c]++;
                if (window[c] == need[c])
                    valid++;
            }

            // 判断左侧窗口是否要收缩
            while (valid == need.size()) {
                // 在这里更新最小覆盖子串
                if (right - left < len) {
                    start = left;
                    len = right - left;
                }
                // d 是将移出窗口的字符
                char d = s[left];
                // 缩小窗口
                left++;
                // 进行窗口内数据的一系列更新
                if (need.count(d)) {
                    if (window[d] == need[d])
                        valid--;
                    window[d]--;
                }
            }
        }
        // 返回最小覆盖子串
        return len == INT_MAX ?
               "" : s.substr(start, len);
    }
};
posted @ 2022-05-22 15:31  mengchao  阅读(29)  评论(0编辑  收藏  举报