一篇文章让你熟练运用滑动窗口思想

我们可以根据算法的题库,快速有一个解题思路

什么样的题目适合滑动窗口思想?

关键词:

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

最长/最短

字串/子数组/子序列

例如:长度最小的子数组

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

-----核心:左右双指针(L,R)在起始点,R向右逐位滑动循环

-----每次滑动的过程中

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

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

------R到达结尾

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

-----核心:左右双指针(L,R)在起始点,R向右逐位滑动循环

-----每次滑动的过程中

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

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

------R到达结尾

新手的答题模板

视频讲解,请见精心总结滑动窗口代码模板, 直接搞定80道Leetcode算法题_哔哩哔哩_bilibili

力扣

解题代码:

非常好理解,想象两把尺子,错开之后比较相同的部分,找最长相同的串就好了。

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        return nums1.length<=nums2.length? findMax(nums1,nums2):findMax(nums2,nums1);
    }

    public int findMax(int[] nums1, int[] nums2){
        int max=0;
        int m=nums1.length,n=nums2.length;
        /**
        nums1,nums2中较短的数组不动,这里默认nums1,较长的数组滑动
        初始位置:nums2右边界挨着nums1左边界,nums2从左往右滑动
         */
        // 第一阶段:nums2从左往右滑动,两数组重合部分长度不断增加,重合部分长度len从1开始增加
        // 重合部分:nums1起点下标0,nums2起点下标n-len,
        for(int len=1;len<=m;len++){
            max=Math.max(max,maxLen(nums1,0,nums2,n-len,len));
        }
        // 第二阶段:nums2从左往右滑动,两数组重合部分长度不变,重合部分长度始终为nums1长度m
        //  重合部分:nums1起点下标0,nums2起点下标n-m,然后递减
        for(int j=n-m;j>=0;j--){
            max=Math.max(max,maxLen(nums1,0,nums2,j,m));
        }
        // 第三阶段:nums2从左往右滑动,两数组重合部分长度递减,重合部分长度始终为nums1长度m-i
        //  重合部分:nums1起点下标i,递增,nums2起点下标0
        for(int i=1;i<m;i++){
            max=Math.max(max,maxLen(nums1,i,nums2,0,m-i));
        }
        return max;
    }

    /**
    nums1中下标i开始,nums2中下标j开始,长度为len子数组中,最长公共子数组(注意要连续)长度
     */
    public int maxLen(int[] nums1,int i,int[] nums2,int j,int len){
        int count=0,res=0;
        for(int k=0;k<len;k++){
            if(nums1[i+k]==nums2[j+k]){
                count++;
            }else if(count>0){
                //进入到这个if判断体里面,说明当前 nums1[i+k]!=nums2[j+k],即之前的公共子数组不再连续,
                // 所以要记录最大值,同时将count置零
                res=Math.max(count,res);
                count=0;
            }
        }
        /**
        1,count>0,说明有公共子数组是以nums1[i+len-1],nums2[j+len-1]结尾的,
           上面最后一步for循环没有进入到else if判断题里面,所以最终结果要取当前count和res的最大值
        2,count=0,说明res已经更新过了,res即为最终结果
         */
        return count>0? Math.max(count,res):res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值