leetcode刷题1-最长不重复子串

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

起初的想法是通过一个滑动窗口,不停的前进,然后查看下一个字符是否在窗口内,然后判断长度是否是最长的。

但是该方法复杂度较高,后来在阅读提示和解答后,发现在最长只有可能出现在两个重复字符之间,可以过滤大部分的字符,得到的代码如下:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int len = s.length();
        Map<Character, Integer> map = new HashMap<>();
        int max = 0;
        for(int i=0,j=0;i<len;i++){
            if(map.containsKey(s.charAt(i))){
                j = map.get(s.charAt(i))+1;
            }
            max = max < i-j+1 ? i-j+1 : max;
            map.put(s.charAt(i), i);
            
        }
        return max;
    }
}
复制代码

运行后发现对于tmmzuxt这种字符串一直无法成功,想了很久没有想明白,最后单步调试发现,当执行到最后一个t的时候,起始位置一下子移动到了第一个t后面的位置,后修改代码如下

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int len = s.length();
        Map<Character, Integer> map = new HashMap<>();
        int max = 0;
        for(int i=0,j=0;i<len;i++){
            if(map.containsKey(s.charAt(i))){
                //该步骤有两个作用:
                //1.将起始位置j从重复的位置往后移动
                //2.防止起始位置回到最开始的位置,起始位置只能向后递增,不能回溯
                j = Math.max()map.get(s.charAt(i))+1,j);
            }
            max = max < i-j+1 ? i-j+1 : max;
            map.put(s.charAt(i), i);
            
        }
        return max;
    }
}
复制代码

其实该方法的主题思路是:

一开始的理解是最长不重复子串必然是在两个重复的字符之间,所以就没有考虑到起始位置前移的问题;

后来发现,起始位置非常重要,最长的重复子串要么出现在起始位置之前,要么出现在起始位置之后,之前的话已经计算过了最长的子串,之后的话还是要继续计算。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值