算法训练计划--------滑动窗口

目录

前言:

滑动窗口算法:

实战训练:

一、LeetCode:209.长度最小的子数组(Medium)

二、LeetCode:3.无重复字符的最长子串(Medium)

三、LeetCode:1004.最大连续1的个数(Medium)

四、LeetCode:1658.将X减到0的最小操作数 (Medium)

 五、LeetCode:904.水果成篮

六、LeetCode:438.找到字符串中所有字母异位词(Medium)

七、LeetCode:30.串联所有单词的子串(Hard)

八、LeetCode:76.最小覆盖子串(Hard) 

结语:


前言:

        Hello,大家好,我是Go。本文将呈现笔者本人最近在做的滑动窗口算法题。记录一下笔者学习到的题解思路以及附上个人代码,供大家参考及指正。希望对正在学习算法,尤其是滑动窗口算法的同学提供一点帮助。


滑动窗口算法:

        滑动窗口算法换言之就是 left 和 right 指针同向运动的双指针算法。当 left 和 right 指针的同向运动,限定出一块 连续的区间,我们可以在区间内维护和更新结果时,此算法就是滑动窗口算法。

俗话说 Talk is cheap. Show me the code。我们话不多说,直接上题让大家亲身感受一下。


实战训练:

一、LeetCode:209.长度最小的子数组(Medium)

思路:

1、 根据题目的描述和实例的展示,我们可以分析出。我们要分析的是nums中一段连续的区间,判断 区间和 >= target 的最小区间。所以我们可以利用滑动窗口算法解决问题。

2、首先定义两个指针 left = 0 ,right = 0,sum = 0(记录窗口内元素的和)。

每次,先将right指针所在位置元素相加。sun += nums[right]。并判断sum是否大于等于target

每当大于等于 target。就代表 [left,right-1] 此区间的元素和满足条件,那么我们就更新结果。并且窗口缩小(出窗口),也就 left++ 去下一个窗口寻找满足条件的区间。

小于target的话,代表区间元素和不满足条件,需要继续扩大窗口,也就是 right++。

拿示例一:【2,3,1,2,4,3】举例。区间内元素为 2 3 1 2 时,sum=8 > target。

此时能满足条件的最小区间便是 2 3 1 2。那么此时以2为基准的窗口已经没用了,那么我们就可以将窗口滑动,以3为基准找到满足条件的最小区间。于是找到 3 1 2 4 这个窗口。循环往复直到 r > nums.length-1

图解:

代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int l = 0,r = 0,n = nums.length,min = n+1,sum=0;
        while(r<n){
            //进窗口
            sum += nums[r];
            while(sum>=target){
                //判断,更新长度
                min = Math.min(min,r-l+1);
                //出窗口 窗口向右缩减
                sum-=nums[l++];
            }
            //窗口向右扩张
            r++;
        }
        //如果min大于n 表示没有符合的区间,返回0
        return min>n ? 0 : min;
    }

}

二、LeetCode:3.无重复字符的最长子串(Medium)

思路:

1、从题目可看出,我们分析的是字符串中,连续的无重复的最长区间,所以便可以想到利用滑动窗口。同时为了保证无重复字符(或者说是每个字符只出现一次),就需要哈希表来记录每个字符出现的次数。保证字符唯一

2、定义 left = 0 , right = 0;每次右端字符ch,进入窗口时,都将其放入哈希表中查看出现的次数。

如果该字符存在过(即哈希表key对应的value>1),就缩小窗口,寻找不存在重复字符的区间。

如果该字符没存在过,则代表此区间无重复字符,更新结果。随后继续扩大窗口

代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //将字符串转换成字符数组
        char[] ss = s.toCharArray();
        //使用数组模拟哈希表
        int[] hash = new int[128];
        int l = 0,r = 0,max =0,n =ss.length;
        while(r<n){
            //入窗口,并在对应处设置哈希值
            hash[ss[r]]++;
            //判断
            while(hash[ss[r]]>1){
                //将左端点的数据删除,并出窗口
                hash[ss[l++]]--;
            }
            max = Math.max(max,r-l+1);
            r++;
        }
        return max;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值