滑动窗口解题

滑动窗口

理论讲解

算法的应用场景

满足XXX条件(计算结果,出现次数,同时包含)

出现最长,最短时

字串/子数组/子序列

如:长度最小的子数组

滑动窗口的使用思路(寻找最长)

**核心:**左右双指针(L,R)最开始在起始点,然后R向右诸位滑动循环

每次滑动过程中

如果窗内元素满足条件,R向右扩大窗口,并更新最优结果

如果窗内元素满足条件,L向右,缩小窗口

R到达结尾

最长模板

初始化left,right,result,bestRresult
while(右指针没有到结尾){
	窗口扩大,加入right对应的元素,更新result//该位置要视情况而定,也可以放到while循环下面
	while(result不满足要求){
		窗口缩小,移除left对应元素,left右移
	}
	更新最优结果bestResult
	right++;
}

例题:3. 无重复字符的最长子串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DeEqub5g-1661679992517)(C:\Users\wu\AppData\Roaming\Typora\typora-user-images\image-20220729130905492.png)]

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int l=0,r=0,res=0;
        Set<Character> occ = new HashSet<Character>();
        while(r<s.length()&&l<=r){
            while(occ.contains(s.charAt(r))){
                occ.remove(s.charAt(l));
                l++;
            }
            occ.add(s.charAt(r));
            res=r-l+1>res?r-l+1:res;
            r++;
        }
        return res;
    }
}

滑动窗口的使用思路(寻找最短)

**核心:**左右双指针(L,R)最开始在起始点,然后R向右诸位滑动循环

每次滑动过程中

如果窗内元素满足条件,L向右缩小窗口并更新最优结果

如果窗内元素满足条件,R向右扩大窗口

R到达结尾

最短模板

初始化left,right,result,bestRresult
while(右指针没有到结尾){
	窗口扩大,加入right对应的元素,更新result
	while(result满足要求){
        更新最优结果bestResult
		窗口缩小,移除left对应元素,left右移
	}
	right++;
}

例题:209. 长度最小的子数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-86eUzp0A-1661679992519)(C:\Users\wu\AppData\Roaming\Typora\typora-user-images\image-20220729131107814.png)]

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left=0,right=0;
        int sum=0;
        int res=nums.length+1;
        while(right<nums.length){
            sum=sum+nums[right];
            while(sum>=target){
                res=right-left+1<res?right-left+1:res;
                sum=sum-nums[left];
                left++;
            }
            right++;
        }
        return res==nums.length+1?0:res;
    }
}

另一种模板

滑动窗口有两种解决问题的思想

其一:

左指针一次移动一格**for(int L=0,L<length,L++)**然后右指针按照要求遍历左指针之后的元素.

右指针R在【L,end】的区间内,搜索结果。一般时while循环中自增R++。直到不满足循环条件

3. 无重复字符的最长子串的另一种解法

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 哈希集合,记录每个字符是否出现过
        Set<Character> occ = new HashSet<Character>();
        int n = s.length();
        // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        int rk = -1, ans = 0;
        for (int i = 0; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格,移除一个字符
                occ.remove(s.charAt(i - 1));
            }
            while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                // 不断地移动右指针
                occ.add(s.charAt(rk + 1));
                ++rk;
            }
            // 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = Math.max(ans, rk - i + 1);
        }
        return ans;
    }
}

其二:

右指针一次移动一格**for(int R=0,R<length,R++)**然后左指针按照要求遍历右指针之前的元素.

左指针R在【0,R】的区间内,搜索结果。一般时while循环中自增L++。直到不满足循环条件

209. 长度最小的子数组的另一种解法

class Solution {
    // 滑动窗口
    public int minSubArrayLen(int s, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= s) {
                result = Math.min(result, right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值