[LeetCode] 3. 无重复字符的最长子串

Posted lijiong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 3. 无重复字符的最长子串相关的知识,希望对你有一定的参考价值。




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

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是?"wke",所以其长度为 3。
?    请注意,你的答案必须是 子串 的长度,"pwke"?是一个子序列,不是子串。

分析

  1. 双指针,通过set保存字符,需考虑第二个指针到最后的情况

  2. 滑动窗口,若某元素在 [i, j) 范围内有重复字符,则将i变为该元素在范围内索引加1

解法

解法一

  • 双指针,通过set保存字符

  • 时间复杂度O(n)

  • 空间复杂度O(min(m,n)),m和n分别为字符集大小和字符串大小

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s.length() == 0) return 0;
        char[] arr = s.toCharArray();
        int max = 1;
        // i为每个子串的起点
        for(int i = 0; i < arr.length-1; i++){
            // 保存字符
            HashSet<Character> set = new HashSet<>();
            set.add(arr[i]);
            // j为每个子串的终点
            for(int j = i+1; j < arr.length; j++){
                if(set.contains(arr[j])){
                    if(j - i > max){
                        max = j - i;
                    }
                    break;
                }
                // j到最后的情况
                if(j == arr.length-1){
                    if(j - i + 1 > max){
                        max = j - i + 1;
                    }
                    break;
                }
                set.add(arr[j]);
            }
        }
        return max;
    }
}

//class Test{
//    public static void main(String[] args) {
//        Solution s = new Solution();
//        int res = s.lengthOfLongestSubstring("abcabcbb");
//        System.out.println(res);
//    }
//}

解法二

  • 右指针每移动一次,检查左指针到右指针有没有和右指针重复的,若有,将左指针变为重复索引加1

  • 时间复杂度O(n)

  • 空间复杂度O(1)

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int max = 0;
        char[] chars = s.toCharArray();
        int left = 0;
        for (int right = 0; right < s.length(); right++) {
            for (int i = left; i < right; i++) {
                if (chars[i] == chars[right]) {
                    // left至right-1为无重复子串,长度为right-left
                    max = Math.max(max, right - left);
                    left = i + 1;
                    break;
                }
            }
        }
        // max以重复字符为判断,需考虑无重复情况
        return Math.max(s.length() - left, max);
    }
}

解法三

  • 滑动窗口

  • 时间复杂度O(n)

  • 空间复杂度O(min(m,n))

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int ans = 0;
        // k:v为字符:索引
        Map<Character, Integer> map = new HashMap<>();
        for (int left = 0, right = 0; right < s.length(); right++) {
            if (map.containsKey(s.charAt(right))) {
                // 若重复字符不在当前的子串中(索引小于left),left保持不变
                // 若重复字符在当前子串中,left变为子串中该字符索引加1
                left = Math.max(map.get(s.charAt(right)) + 1, left);
            }
            ans = Math.max(ans, right - left + 1);
            map.put(s.charAt(right), right);
        }
        return ans;
    }
}

解法四

  • 滑动窗口+ASCII128

  • 时间复杂度O(n)

  • 空间复杂度O(m),m为字符集大小

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int ans = 0;
        // 存储元素为字符在字符串中的最新位置
        Integer[] index = new Integer[128];
        for (int left = 0, right = 0; right < s.length(); right++) {
            // 相应值不为null,则字符重复
            if(index[s.charAt(right)] != null){
                // 若重复字符不在当前的子串中(索引小于left),left保持不变
                // 若重复字符在当前子串中,left变为子串中该字符索引加1
                left = Math.max(index[s.charAt(right)] + 1, left);
            }
            ans = Math.max(ans, right - left + 1);
            index[s.charAt(right)] = right;
        }
        return ans;
    }
}


以上是关于[LeetCode] 3. 无重复字符的最长子串的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 无重复字符的最长子串

[LeetCode]无重复字符的最长子串

leetcode题解#3:无重复字符的最长子串

Python版[leetcode]3. 无重复字符的最长子串(难度中等)

LeetCode3. 无重复字符的最长子串

力扣Leetcode 3. 无重复字符的最长子串