Leetcode第三题 Longest Substring Without Repeating Characters 最长不重复子串

459 阅读2分钟

题目描述:给定一个字符串,求出改字符长中最长的,字符不重复的子串。

解题思路:这个题的关键,是对重复字符的处理,在遍历字符串的过程中,遇到了重复的字符时,需要把 已存在的重复字符和它之前的字符全删掉,从而保证新得到的字符时没有重复的。

例: abcbmc
第一次遍历:a
第二次遍历:ab
第三次遍历:abc
第四次遍历:cb 这个时候要删除前一个b和这个下标之前的字符,保证新子串是没有重复的
第五次遍历:cbm
第六次遍历:bmc 同第四次遍历,要删除前一个c和这个下标之前的字符,保证新子串是没有重复的 代码如下,这个比较好理解.

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s.length() == 0){
            return 0;
        }
        int subLength=0;
        int left=0;
        Set<Character> set=new HashSet<>();
        
        for(int i=0 ; i<s.length() ; i++){
            Character chars=s.charAt(i);
            while(set.contains(chars)){
                set.remove(s.charAt(left++));
            }
            set.add(chars);
            if(set.size() > subLength){
                subLength=set.size();
            }
        }
        return subLength;
    }
}

运行结果: Runtime: 11 ms, faster than 35.25% of Java online submissions for Longest Substring Without Repeating Characters.

Memory Usage: 43.2 MB, less than 8.69% of Java online submissions for Longest Substring Without Repeating Characters. 这个解法性能相对较差。

第二种解法:我们其实只需要关心一个核心的问题。出现重复字符之后,重复字符的下标是什么值,获取到对应的值以后,就能算出当前不重复子串的长度。可以把上边解法的while循环干掉。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int result=0;
        int[] arr=new int[256];
        
        for(int i=0,j=0;i<s.length();i++){
            //先获取下左下标,arr[s.charAt(i)]是指当前字符上一次出现的位置
            j= Math.max(j,arr[s.charAt(i)]);
            //把当前字符的下标更新到数组,需要+1,因为如果后面出现重复了,计算长度不会包含当前字符
            arr[s.charAt(i)]=i+1;
            //对比下当前子串和历史长度,区个最大值
            result=Math.max(result,i-j+1);
        }
        return result;
    }
}

运行结果: Runtime: 2 ms, faster than 99.75% of Java online submissions for Longest Substring Without Repeating Characters.

Memory Usage: 38.9 MB, less than 94.53% of Java online submissions for Longest Substring Without Repeating Characters.