java算法合集-九阳神功第三式滑动窗口

本文介绍了滑动窗口方法,通过五个实际问题(长度最小子数组、无重复字符子串、连续1的最大子数组、K不同字符子串和最少交换次数)展示如何利用滑动窗口优化查找过程。理解并掌握这种方法有助于解决字符串和数组相关的问题,提高效率。
摘要由CSDN通过智能技术生成

5 九阳神功第三式 :滑动窗口
5.1 滑动窗口介绍
出处:(https://zhuanlan.zhihu.com/p/61564531)
滑动窗口法,也叫尺取法(可能也不一定相等,大概就是这样),可以用来解决一些查找满足一定条件的连续区间的性质(长度等)的问题。由于区间连续,因此当区间发生变化时,可以通过旧有的计算结果对搜索空间进行剪枝,这样便减少了重复计算,降低了时间复杂度。往往类似于“请找到满足xx的最x的区间(子串、子数组)的xx”这类问题都可以使用该方法进行解决。
5.1.1 长度最小的子数组(#209)
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。示例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

一旦知道这个位置开始的子数组不会是最优答案了,我们就可以移动左端点。我们用 2 个指针,一个指向数组开始的位置,一个指向数组最后的位置,并维护区间内的和 sum 大于等于 ss 同时数组长度最小。

5.1.2 无重复字符的最长子串(#3)
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

5.1.3 最大连续1的个数 III(#1004)
给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释: [1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
5.2 代表题目:尽可能使字符串相等(#1208)

5.3 触类旁通
5.3.1 至多包含 K 个不同字符的最长子串(#340会员_困难)

/*

  • Copyright © Huawei Technologies Co., Ltd. 2012-2018. All rights reserved.

  • Description: 项目 LEET_340_LongestSubstringforKDiffChar 的源文件

  • Author: f00485759

  • Create: 2019-12-16
    */
    #include <stdio.h>
    #include <stdbool.h>
    #include “securec.h”
    #define MAX_HASH_NUM 256
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    int g_hash[MAX_HASH_NUM];
    void Init(void)
    {
    (void)memset(g_hash, 0, sizeof(g_hash));
    }
    void HashChar(char c)
    {
    g_hash[c]++;
    }
    void DeHashChar(char c)
    {
    if (g_hash[c] > 0) {
    g_hash[c]–;
    }
    }
    bool IsExtendKChar(int k)
    {
    int count = 0;
    for (int i = 0; i < MAX_HASH_NUM; i++) {
    if (g_hash[i] != 0) {
    count++; // 可以通过变量来记忆,减少计算量
    }
    if (count >= k) {
    return true;
    }
    }

    return false;
    }

bool IsRepeat(char c)
{
if (g_hash[c] != 0) {
return true;
}

return false;

}
int lengthOfLongestSubstringKDistinct(const char *s, int k)
{
int start, end, maxlen;
int slen = (int)strlen(s);
Init();
start = 0;
maxlen = 0;
for (end = 0; end < slen; end++) {
if (!IsExtendKChar(k) || IsRepeat(s[end])) {
HashChar(s[end]);
continue;
}

    if (start == end) {
        break;
    }

    maxlen = MAX(maxlen, end - start);
    DeHashChar(s[start]);
    start++;

    while (IsExtendKChar(k)) {
        DeHashChar(s[start]);
        start++;
    }
    HashChar(s[end]);
}
maxlen = MAX(maxlen, end - start);
return maxlen;

}
int main()
{
const char *s = “a”;
int k = 0;

int maxlen = lengthOfLongestSubstringKDistinct(s, k);

printf("%d\n", maxlen);

return 0;

}
5.3.2 最少交换次数来组合所有的 1(#1151会员)

5.3.3 至多包含两个不同字符的最长子串(#159会员)

5.3.4 长度为 K 的无重复字符子串(#1100会员)

#define MAX_LEN 512
int g_array[MAX_LEN];

int numKLenSubstrNoRepeats(char * s, int k){
int right = 0;
int left = 0;
int result = 0;
int count = 0;
int len;

len = strlen(s);
memset(g_array, 0, sizeof(g_array));

while (right < len) {
    if (g_array[s[right]] == 0) {
        count++;    
    }
    g_array[s[right]]++;
    while (right - left + 1 > k) {
        g_array[s[left]]--;
        if (g_array[s[left]] == 0) {
            count--;
        }
        left++;
    }

    printf("%d, %d, %d\n", right, left, count);
    if ((right - left + 1 == k) && (count == k)) {
        result++;
    }

    right++; 
}

return result;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值