数据结构——滑动窗口

定长滑窗套路:入 - 更新 - 出

  • 入:下标为 i 的元素进入窗口,更新相关统计量。如果 i < k−1 则重复第一步
  • 更新:更新答案。一般是更新最大值 / 最小值
  • 出:下标为 i−k+1 的元素离开窗口,更新相关统计量

✔1. 定长子串中元音的最大数目

数据结构——滑动窗口_第1张图片
数据结构——滑动窗口_第2张图片

代码实现:

方法一:暴力解法 —— 超时

int maxVowels(char *s, int k) {
    int res = 0;
    int n = strlen(s);
    for (int i = 0; i < n - k + 1; i++) {
        int sum = 0;
        for (int j = i; j < i + k; j++) {
            if (s[j] == 'a' || s[j] == 'e' || s[j] == 'i' || s[j] == 'o' || s[j] == 'u') {
                sum++;
            }
        }
        res = fmax(res, sum);
        if (res == k) {
            break;
        }
    }
    return res;
}

方法二:滑动窗口

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

int maxVowels(char *s, int k) {
    int ans = 0, sum = 0;
    for (int i = 0; s[i]; i++) {
        // 1. 进入窗口
        if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
            sum++;
        }
        if (i < k - 1) { // 窗口大小不足 k
            continue;
        }
        // 2. 更新答案
        ans = max(ans, sum);
        if (ans == k) {
            break;
        }
        // 3. 离开窗口
        char out = s[i - k + 1];
        if (out == 'a' || out == 'e' || out == 'i' || out == 'o' || out == 'u') {
            sum--;
        }
    }
    return ans;
}

✔2. 找到一个数字的 K 美丽值

数据结构——滑动窗口_第3张图片
数据结构——滑动窗口_第4张图片

代码实现:

方法一:暴力解法

int divisorSubstrings(int num, int k) {
    int ret = 0;
    char buff[11] = {0};
    sprintf(buff, "%d", num);
    int n = strlen(buff);
    for (int i = 0; i < n - k + 1; i++) {
        int temp = 0;
        for (int j = i; j < i + k; j++) {
            temp = temp * 10 + (buff[j] - '0');
        }
        if (temp != 0 && num % temp == 0) {
            ret++;
        }
    }
    return ret;
}

方法二:滑动窗口

int divisorSubstrings(int num, int k) {
    int ret = 0;
    char buff[11] = {0};
    sprintf(buff, "%d", num);
    int n = strlen(buff);
    int temp = 0;
    for (int i = 0; i < n; i++) {
        // 1. 进入窗口
        temp = temp * 10 + (buff[i] - '0');
        if (i < k - 1) { // 窗口大小不足 k
            continue;
        }
        // 2. 更新答案
        if (temp != 0 && num % temp == 0) {
            ret++;
        }
        // 离开窗口
        int out = buff[i - k + 1] - '0';
        for (int j = 0; j < k - 1; j++) {
            out *= 10;
        }
        temp -= out;
    }
    return ret;
}

3. 学生分数的最小差值

数据结构——滑动窗口_第5张图片
数据结构——滑动窗口_第6张图片

代码实现:

int minimumDifference(int *nums, int numsSize, int k) {
    if (k == 1) {
        return 0;
    }
    int min = INT32_MAX;

    // 冒泡排序
    int flag = 1;
    for (int i = numsSize - 1; i > 0; i--) {
        flag = 0;
        for (int j = 0; j < i; j++) {
            if (nums[j] > nums[j + 1]) {
                flag = 1;
                int temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
    for (int i = k - 1; i < numsSize; i++) {
        // 更新答案
        int ret = nums[i] - nums[i - k + 1];
        if (min > ret) {
            min = ret;
        }
    }
    return min;
}

4. 子数组的最大平均数 |

数据结构——滑动窗口_第7张图片

代码实现:

double findMaxAverage(int *nums, int numsSize, int k) {
    double res = INT32_MIN;
    double sum = 0;
    for (int i = 0; i < numsSize; i++) {
        // 1. 进入窗口
        sum += nums[i];
        if (i < k - 1) { // 窗口大小不足k
            continue;
        }
        // 2. 更新答案
        res = fmax(res, sum / k);
        // 3. 离开窗口
        sum -= nums[i - k + 1];
    }
    return res;
}

5. 大小为 K 且平均值大于等于阈值的子数组数目

数据结构——滑动窗口_第8张图片
数据结构——滑动窗口_第9张图片

代码实现:

int numOfSubarrays(int *arr, int arrSize, int k, int threshold) {
    int res = 0;
    double sum = 0;
    for (int i = 0; i < arrSize; i++) {
        // 1. 进入窗口
        sum += arr[i];
        if (i < k - 1) { // 窗口大小不足k
            continue; 
        }
        // 2. 更新答案
        if (sum / k >= threshold) {
            res++;
        }
        // 离开窗口
        sum -= arr[i - k + 1];
    }
    return res;
}

6. 半径为 k 的子数组平均值

数据结构——滑动窗口_第10张图片

数据结构——滑动窗口_第11张图片

数据结构——滑动窗口_第12张图片

代码实现:

方法一:前缀和

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* getAverages(int *nums, int numsSize, int k, int *returnSize) {
    int *res = malloc(sizeof(int) * numsSize);
    memset(res, -1, sizeof(int) * numsSize);
    *returnSize = numsSize;

    // 前缀和
    long arr[numsSize];
    arr[0] = 0;
    for (int i = 1; i < numsSize; i++) {
        arr[i] = arr[i - 1] + nums[i - 1];
    }

    for (int i = k; i < numsSize - k; i++) {
        long sum = arr[i + k] + nums[i + k] - arr[i - k];
        res[i] = sum / (2 * k + 1);
    }
    return res;
}

方法二:滑动窗口

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* getAverages(int *nums, int numsSize, int k, int *returnSize) {
    int *res = malloc(sizeof(int) * numsSize);
    memset(res, -1, sizeof(int) * numsSize);
    *returnSize = numsSize;

    int size = 2 * k + 1;
    if (size > numsSize) {
        return

你可能感兴趣的:(数据结构与算法,数据结构)