无重复字符的最长子串(力扣3)

本文介绍了LeetCode第3题——无重复字符的最长子串问题的解法。通过滑动窗口策略,利用左右指针移动,判断字符是否在窗口集合中,从而找到最长不重复子串的长度。详细解析了关键步骤,并提供了代码实现。
摘要由CSDN通过智能技术生成

题目描述

题目链接:力扣https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

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

解法

对于平时不刷题的朋友们来说,此题属于如果之前没见过,凭借面试中短短十几二十分钟想真的自己做出来,基本不可能的那种题目。

对于这种题目,我只有一个办法,搞懂思路,反复编码,直到形成肌肉记忆。

不要太高估自己,就算记得思路,面试的时候你想 bug free 一次过,都是有难度的。

下面,我来总结一下此题应该记住的关键点:

        1.滑动窗口,一般来说,要一个字符串的连续子串满足啥条件的题目,都可以用该解法。基本思路是,用一头一尾俩指针框定一个范围,然后右指针不停右移,直到不满足条件为止,这时候左指针再跟着右移,直到又重新满足条件。

        判断是否满足条件,利用的是一个窗口,也就是一个集合,它是左右指针之间的所有元素的集合;

        2.在本题中,窗口保存的是左右指针的闭区间;

        3.循环结束条件,是右指针到达字符串尾部,而且结束后要再判定一次窗口的长度;

        3.移动右指针的时候 ,将当前右指针指向的字符加入窗口;

        4.当右指针指向的字符在窗口中出现过时,开始移动左指针,直到左指针越过该字符在最近一次出现的位置,同时,要把左指针越过的字符统统从窗口移除。这个重复的字符就不用移除了,因为右指针越过它,本来是要把它加入窗口的,我们左指针不移除,右指针就不用再加入了,省了两个操作。

代码

class Solution {
    public  int lengthOfLongestSubstring(String s) {
        // 参数校验
        if(s == null){
            return 0;
        }
        int len = s.length();
        if(len <= 1){
            return len;
        }
      

        // 初始化左右指针,其实模拟的是左右指针都指向第一个字符,
        // 这时候右指针右移了一位
        int l = 0;
        int r = 1;

        // 维护一个窗口,我们只判定窗口内的字符串是否不含重复字符
        // 窗口里的内容是左右指针的闭区间
        Set<Character> window = new HashSet<>();
        // 先把第一个字符放进去,对第二个字符的处理,就在 while 循环中了
        window.add(s.charAt(0));
        int ans = 1; // 返回结果最小是1,很容易理解,单个字符就是长度为1的无重复字符的子串

        // 右指针指向字符串最后一个字符时进行最后一次循环
        while(r < len){
            char temp = s.charAt(r);
            if(!window.contains(temp)){
                // 如果窗口中没有右指针指向的字符,将其加入窗口
                window.add(temp);
            } else {
                // 如果碰到重复字符,那么立刻更新结果,看看当前窗口长度是不是比现有结果更大
                ans = Math.max(ans, window.size());
                // 将左指针移动到第一次出现重复字符的位置的后一位
                while(s.charAt(l) != temp){
                    // 不在左右指针之间的字符,要清除出窗口
                    window.remove(s.charAt(l++));
                }
                
                // 将左指针指向重复字符的后一位,这里没将其移出窗口
                // 因为我们也没有将右指针指向的下一个该字符放进窗口
                // 所以这里不移出,就当移出又放进去了,没啥区别
                l++;
            }
            r++;
        }
        // 万一右指针到头了,但是最后却没遇到重复字符,上面的 else 分支最后就没走到
        // 因此单独判定一下
        ans = Math.max(ans, window.size());
        return ans;
    }
}

现在,关于无重复字符的最长子串这道题,你已经知道得和我一样多了~

本专栏定期更新力扣算法讲解,希望以最容易记忆的方式帮你搞定面试算法题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值