滑动窗口 算法

滑动窗口算法

适用场景:

求解子串、子数组、子序列等问题

算法核心思想:

利用左右指针,维护一个窗口,不断移动寻找解集。首先不断增加右窗口指针right来扩大窗口,直到窗口符合要求。之后停止right, 增加左窗口指针left来缩小窗口。每次增加left都需要进行更新。

算法模板:

func(XX)
{

    // 初始化变量
    int left = 0;
    int right = 0;
    int res = INT_MIN; // 题目求最长子串/子数组
    int cur_val;
    ...
      
    // 初始化窗口容器 统计量
    // vector string
    // unordered_map<,> m; // hash常用于统计出现次数、是否存在、是否覆盖、是否匹配
    // int count;
    
    // 
    while (right < XX.size()) {
        cur_val = XX[right];
        right++;
        
        // 更新容器或者统计数据 (添加、增加)
        
        while (condition) { //condition 为缩小窗口的条件
            
            // 更新res (根据具体场景)
            
            // 更新容器或者统计数据 (移除, 减少)
            
            left++;
        }
        
        // 更新res (根据具体场景)
    
    }
    
    // 更新res (根据具体场景)
    return res;
}

常见的窗口收缩方法:
 

(1) c重复出现时开始收缩窗口
    window[cur_val]++; // 容器统计出现的次数
    while (window[cur_val] > 1) { // 收缩条件为 重复出现
        cur_val = left的值;
        window[cur_val]--;
        left++;
    }

(2) 至多(最多)包含问题
    window[cur_val]++; // 容器统计出现的次数
    if (window[cur_val] == 1) count++; // 统计不同字符的个数
     while(count > k) { // 最多包含k个不同字符
         // 更新res (根据具体场景)
         cur_val = left的值;
         window[cur_val]--;
         if (window[cur_val] == 0) count--;
         left++;
     }

(3) 重复序列问题
    cur_str += right的值; // 当前序列不断更新
    while (当前序列满足要求) {
        m[cur_str]++;
        if (m[cur_str] 重复) {
            // 找到了当前序列的重复项
            // 更新
        }     
        left++; // 缩小
        cur_str = cur_str[1, right - left]; // 更新为新的序列
    }

(4)长度为 k 的连续子数组
	cur_sum += cur_val; 
	while ((right - left) == k) { // 子数组长度为k,满足要求,可以缩小了
		cur_sum = cur_sum - left的值;
		left++; 
	} 

 (5) 最多可以替换/翻转k个元素,组成连续相同元素序列。
	if (right的值是目标连续的值)count++;
	while(left - right - count > k) {
		// res
		if (left的值是目标连续的值) count--;
		left++;
 	}

必学必会算法题:

无重复字符的最长子串
https://leetcode.cn/problems/longest-substring-without-repeating-characters/

至多包含两个不同字符的最长子串
https://leetcode.cn/problems/longest-substring-with-at-most-two-distinct-characters/

重复的DNA序列
https://leetcode.cn/problems/repeated-dna-sequences/

长度最小的子数组
https://leetcode.cn/problems/minimum-size-subarray-sum/

存在重复元素 II
https://leetcode.cn/problems/contains-duplicate-ii/

至多包含 K 个不同字符的最长子串
https://leetcode.cn/problems/longest-substring-with-at-most-k-distinct-characters/

最大连续1的个数 II
https://leetcode.cn/problems/max-consecutive-ones-ii/

子数组最大平均数 I
https://leetcode.cn/problems/maximum-average-subarray-i/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值