滑动窗口方法

本文通过实例解析了滑动窗口方法在字符串排列检测(是否包含s1的排列)和无重复字符最长子串问题中的应用。通过创建计数数组跟踪字符数量,演示了如何利用窗口滑动实现高效判断。后续还涉及了HashSet在重复字符检测中的作用。
摘要由CSDN通过智能技术生成

滑动窗口方法一般是用在要求最值,或者子序列

力扣的一道算法题,我觉得可以很好的理解滑动窗口 

字符串的排列:给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。换句话说,s1 的排列之一是 s2 的 子串 。

先分析一哈,为啥要用滑动窗口,这道题要求一个字符串是否包含另一个的排列,而对于排列来说,并不会改变字符串里各个字母的数量比如:字符串ab,他的另一个排列是ba,但是不管怎么排列,字母a的数量是1,字母b的数量是1。所以对于本题来说,就创建两个int数组来记录每个字符的数量,随后,我们创建一个s1大小的窗口,滑动窗口每向右滑动一次,就多统计一次进入窗口的字符,少统计一次离开窗口的字符。

补充一点:当判断两数组是否相等时,当对数组名称使用 == 运算符时,运算符会比较数组的开始内存地址,而不是数组的内容。这个代码中的两个数组显然会有不同的内存地址,所以当数组相等时,也会返回false,所以我们就用Arrays的equals()方法

我们了解一下代码:

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        int n1=s1.length(),n2=s2.length();
        if(n1>n2){
            return false;
        }
        int[] cnt1=new int[26];
        int[] cnt2=new int[26];
        for(int i=0;i<n1;i++){
            cnt1[s1.charAt(i)-'a']++;
            cnt2[s2.charAt(i)-'a']++;
        }
        if(Arrays.equals(cnt1,cnt2)){
            return true;
        }

        //这里就是开始所谓的窗口滑动

        for(int i=n1;i<n2;i++){
            cnt2[s2.charAt(i)-'a']++;
            cnt2[s2.charAt(i-n1)-'a']--;
            if((Arrays.equals(cnt1,cnt2))){
            return true;
        }
        }
        return false;
    }
}

在了解了前一道题以后再来一题感受一下:

无重复字符的最长字串 :给定一个字符串 s,请你找出其中不含有重复字符的 最长子串 的长度。

分析:题目要求说不含有重复字符的最长字串说到字串是不是感觉很眼熟,是的,这道题也属于滑动窗口的范围,但是这道题不同之处在于,这道题用right作为一个指针,不断地向右滑动将获得的字符串加入到ch中,当遇到重复的字符串时,就将现在的right+1减去i,以为是将right初始值设为-1,减去已经去除的前面的字符个数i,将这时的值与answer取一个最大值。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> ch = new HashSet<>();
        int answer=0;
        int right=-1;
        int n=s.length();
        for(int i=0;i<n;i++){
            if(i!=0){
                ch.remove(s.charAt(i-1));
            }
            while(right+1<n && !ch.contains(s.charAt(right+1))){
                ch.add(s.charAt(right+1));
                right++;
            }
            answer=Math.max(answer,right+1-i);
        }
        return answer;
    }
}

那就这么多,欧了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值