leetCode 3.无重复字符的最长子串(利用滑动窗口遍历非重复子串)

本文探讨了一种高效算法,通过滑动窗口法遍历字符串,寻找最长的无重复字符子串。对比了暴力求解法,介绍了滑动窗口的原理及其实现,显著提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这道题看起来很容易,就是给一个字符串,然后找子串,比较找出最长的子串。

这就涉及到了最重要的问题,求子串
如果是简单的求出子串,那么两个for循环嵌套就好了。
第一个for循环给出子串的起始坐标,第二个遍历淄川的终止坐标。
但这个题很有意思,让我们找的是子串有特殊属性:其中所有字符不重复!
那么很有意思,有没有简化的方法来遍历字符不重复的子串

遍历字符不重复的子串

最好的遍历方法就是滑动窗口法
我们来想象一下,有一个可以左右拉伸的窗口,这个窗口的宽度从0开始变大变小,开始的时候,窗口左端边与字符串第一个字符对其,然后窗口的右端边从字符串的第二个字符开始准备向右跑,窗口左端边也准备向右跑,具体怎么跑可以遍历所有不重复子字符串呢?规则如下:
保证窗口内的字符都是不重复的,利用窗口的蠕动变换遍历所有不重复子字符串
右端边遇到的字符不在窗口内,呢么右端边向右一下,把这个不在窗口内的字符包进来,一直重复这个操作(窗口右端不断拉长),直到遇到一个已经在窗口内的字符。这个时候窗口窗口的左端右移,然后继续判断哪个字符是不是在窗口内,如果还在窗口内,窗口左端就继续右移,直到哪个字符不在窗口内,然后窗口右端右移把这个字符包进来,这样一直做,最后窗口的右端到了字符串右边界,即可遍历完所有不重复的子串.

我们先来看看暴力求解的代码:

class Solution{
    public int lengthOfLongestSubstring(String s){
        if(s.isEmpty()){
            return 0;
        }
        int ans=1;
        for(int i=0;i<s.length();i++){
            for(int j=i+1;j<s.length();j++){
                if(isUnique(s,i,j)){
                    if(ans<j-i+1){
                        ans=j-i+1;
                    }
                }
            }
        }
        return ans;
    }
    public boolean isUnique(String str,int index1,int index2){
        boolean result=true;
        Set<Character> mySet=new HashSet<Character>();
        for(int i=index1;i<=index2;i++){
            if(mySet.contains(str.charAt(i))){
                result=false;
            }
            else{
                mySet.add(str.charAt(i));
            }
        }
        return result;
    }
}

果然,系统显示:

在这里插入图片描述
超出了时间限制!,想想也是,这种方法时间复杂度为O(n^3),这样都能过也就没天理了。

滑动窗口遍历非重复子串代码实现

class Solution{
    public int lengthOfLongestSubstring(String s){
        if(s.isEmpty()){
            return 0;
        }
        int length=s.length();
        int i=0;//窗口的左端边
        int j=0;//窗口的右端边
        Set<Character> mySet=new HashSet<Character>();
        int ans=1;
        while(i<length&&j<length){
            if(!mySet.contains(s.charAt(j))){
                mySet.add(s.charAt(j));
                j++;
            }
            else{
                mySet.remove(s.charAt(i));
                i++;
            }
            if(ans<mySet.size()){
                ans=mySet.size();//到这一步,mySet中元素个数就是该子串不重复元素个数
            }
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值