五月集训(第06天)——滑动窗口

滑动窗口

1. 1984. 学生分数的最小差值

    思路:
        先对nums排序,利用长度为k的滑动窗口在数组内向右平移,每次算出窗口左右端的差即为分数差值,取其中最小值返回即可。

class Solution {
public:
    int minimumDifference(vector<int>& nums, int k) {
        int n = nums.size();
        int i = 0, j = -1;
        int ans = 1e5+10;
        sort(nums.begin(), nums.end());
        while (j < n - 1) {
            j ++;
            if (j - i + 1 > k) i++;
            if (j - i + 1 == k) ans = fmin(ans, nums[j] - nums[i]); 
        }
        return ans;
    }
};

2. 1876. 长度为三且各字符不同的子字符串

    思路:
        利用长度为3的滑动窗口在字符串上向右平移,判断窗口内的三个字符是否相等,不相等则结果加一。

class Solution {
public:
    int countGoodSubstrings(string s) {
        int len = s.length();
        int i = 0, j = -1;
        int ans = 0;
        while (j < len - 1) {
            j ++;
            if (j - i + 1 > 3) i++;
            if (j - i + 1 == 3){
                if (s[j] != s[j - 1] && s[j] != s[j - 2] && s[j - 1] != s[j - 2])  
                    ans ++;
            }
        }
        return ans;
    }
};

3. 1839. 所有元音按顺序排布的最长子字符串

    思路:
        利用一个变长的滑动窗口,窗口向右扩展
                1) 如果新加入的元音字母是当前元音字母的下一个,则type++
                2) 如果新加入的元音字母与前元音字母相同,则继续向后扩展
                3) 其他情况视为不合法的扩展,收紧窗口,重新扩张left = right


class Solution {
public:
    int get_index(char ch) {
        switch (ch) {
            case 'a': return 1;
            case 'e': return 2;
            case 'i': return 3;
            case 'o': return 4;
            case 'u': return 5;
        }
        return 0;
    }

    int longestBeautifulSubstring(string word) {
        int len = word.length();
        int left = 0, right = 0;
        int ans = 0;
        int type = 1;
        while (right < len - 1) {
            right ++;
            if (get_index(word[right]) - get_index(word[right - 1]) == 1) {
                type ++;
            } else if (get_index(word[right]) - get_index(word[right - 1]) != 0){
                left = right;
                type = 1;
            }
            if (type == 5 && word[right] == 'u') ans = max(ans, right - left + 1);
            //printf("a='%c' right=%d type=%d ans=%d\n", word[right], right, type, ans);
        }
        return ans;
    }
};

4. 1052. 爱生气的书店老板

    思路:
        利用前缀和数组customerGru[i]记录不释放技能时前i满意的顾客数,利用customerSum[i]记录前i天总的顾客数。利用一个长度为minutes的滑动窗口向右移动,这个窗口内的几天老板都不会生气,所以让这些天内来的顾客都满意,所以用customerSum[j] - customerSum[i - 1]代替customerGru[j] - customerGru[i - 1]作为i~j天内满意的顾客数

    解法1:
        利用数组记录前缀和

class Solution {
    #define maxn 20005
public:
    int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
        int n = customers.size();
        int customerGru[maxn];
        int customerSum[maxn];
        for (int i = 1; i <= n; i++) {
            int index = i - 1;
            customerGru[i] = customerGru[index] + (!grumpy[index]) * customers[index];
            customerSum[i] = customerSum[index] + customers[index];
        }
        int i = 1, j = 0;
        int ans = 0, temp;
        while (j < n) {
            j ++;
            if (j - i + 1 > minutes) i++;
            if (j - i + 1 == minutes) {
                temp = customerGru[n] - (customerGru[j] - customerGru[i - 1]) + customerSum[j] - customerSum[i - 1];
                ans = max(ans, temp);
            }
        }
        return ans;
    }
};

    解法2:
        修改原数组,不利用前缀和更新答案。利用变量value获取长度为minutes的窗口中,最大的由技能额外增加的满意的顾客数。最后答案为不放技能时满意的顾客数 + 放技能最多额外增加的满意的顾客数

class Solution {
    #define maxn 20005
public:
    int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
        int n = customers.size();
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (!grumpy[i]) {
                ans += customers[i];
                customers[i] = 0;   // 当天的顾客已经全部满意,不需要在更新
            }
        }
        int i = 0, j = -1;
        int value = 0, sum_minutes = 0;
        while (j < n - 1) {
            j++;
            if (j < minutes) {
                sum_minutes += customers[j];   // 处理窗口小于技能时长的部分
                value += customers[j];
            }
            if (j - i + 1 > minutes) i++;
            if (i != 0 && j - i + 1 == minutes) {
                //printf("j=%d ans=%d ans_new=%d\n", j, ans, ans - customers[j - minutes] + customers[j]);
                sum_minutes = sum_minutes - customers[i - 1] + customers[j];
                value = max(value, sum_minutes);
            }
        }
        return ans + value;
    }
};
posted @ 2022-05-06 08:02  番茄元  阅读(11)  评论(0)    收藏  举报