滑动窗口
滑动窗口

滑动窗口

1、无重复字符的最长子串

(1)题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

(2)解题思路

滑动窗口left right,滑动right,用数组flag存储字符right是否在窗口内出现过,其中right为索引。如果出现过,滑动left,直到符合情况。

(3)代码

#include <string.h>
#define MAX(a, b) ((a) > (b) ? a : b)

int lengthOfLongestSubstring(char* s) {

    int flag[128];
    for (int i = 0; i < 128; i++) flag[i] = 0;

    int n = strlen(s);
    int left = 0;
    int right = 0;
    int maxlen = 0;

    while (right < n && left <= right) {
        
        // 窗口内出现过,不断更新left,直到符合情况
        while (flag[(int)s[right]] == 1) {
            flag[(int)s[left]] = 0;
            left++;
            continue;
        }

        flag[(int)s[right]] = 1;

        maxlen = MAX(maxlen, right - left + 1);

        right++;
    }

    return maxlen;
}

2、爱生气的书店老板

(1)题目描述

有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。在某些分钟内,书店老板会生气。如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。请你返回这一天营业下来,最多有多少客户能够感到满意。

(2)解题思路

答案分为固定收益和额外收益两部分,固定收益很简单。对于额外收益,我们先初始化一个窗口,然后不断滑动,遍历所有窗口,得到所有窗口的额外收益最大值即可。

(3)代码

#define MAX(a, b) ((a) > (b) ? a : b)

int maxSatisfied(int* customers, int customersSize, int* grumpy, int grumpySize, int minutes) {
    // 计算固定收益
    int fixed = 0;

    for (int i = 0; i < grumpySize; i++) {
        if (grumpy[i] == 0) fixed += customers[i];
    }

    // 但是目前多了一个参数minutes 那么我们利用滑动窗口计算额外的收益extra_max
    int c_extra = 0;
    for (int i = 0; i < minutes; i++) {
        if (grumpy[i] == 1) c_extra += customers[i];
    }

    // 滑动窗口
    int extra_max = c_extra;
    for (int i = minutes; i < grumpySize; i++) {
        if (grumpy[i] == 1) c_extra += customers[i]; // 推进
        if (grumpy[i-minutes] == 1) c_extra -= customers[i-minutes]; // 收缩

        extra_max = MAX(extra_max, c_extra);
    }

    return fixed + extra_max;
}

3、双指针滑动窗口

(1)题目描述

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k0,则返回执行操作后数组中连续 1 的最大个数

(2)解题思路

双指针 leftrightright 不断向后移动,直到 k 为 0 时才开始移动 left,期间不断更新答案。

(3)代码

int longestOnes(int* nums, int numsSize, int k) {

    // 初始化
    int left = 0, right = 0;
    int ans = 0;

    // 滑动窗口
    while (right < numsSize) {
        if (nums[right] == 0) k--;

        while (k < 0) {
            if (nums[left] == 0) k++;
            left++;
        }

        int c_ans = right - left + 1;
        if (c_ans > ans) ans = c_ans;

        right++;
    }

    return ans;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注