思路一:(该解法面对最后的大字符串[31000个字符]会超时)

  1. 因为题目中要求取不存在重复字符的最大字符串,第一想法是想理解成贪心问题,总的长度为n,判断k个格子的不重复子字符串是否存在。如求取当1个字符长度的不重复字符串是否存在;2个字符长度的不重复字符串是否存在;3个字符长度的不重复字符串是否存在...n个字符长度的不重复字符串是否存在

代码如下:

// 再次提醒,该解法不能完全解出题目,最后一个大字符串用例因为超时无法通过,仅提供一种实现思路

class Solution {
    public int lengthOfLongestSubstring(String s) {

        // 思路借鉴动态规划划格子方法

        int len = s.length();
        if (len == 0) return 0;
        int max = 1;
	// 最小的格子 1 到最大的格子 len
        for (int i = 1 ; i <= len ; i++) {
	    // 判断该格子下的不重复子字符串是否存在
            for(int start = 0; start <= len - i; start ++ ) {
                char[] copy = new char[i];
                s.getChars(start, start + i,copy,0);
                if(unRepeat(copy)) {
                    max = i;
		    break;
                }
            }
        }
        return max;
    }
    // 重复返回false
    boolean unRepeat(char[] chars) {
        Set s = new HashSet();
        for (char ch: chars) {
            if(!s.contains(ch)) {
                s.add(ch);
            } else {
                return false;
            }
        }
        return true;
    }
}

思路二(正规题解)
使用滑动窗口解决问题

  1. 设置变量记录滑动过程中的子字符串最大值
  2. 该字符串最长子串是不定变化的,因此在遇到重复字符串的时候需要修改滑动窗口的大小,即把窗口的最左边界进行调整
  3. 调整的方法是将left边界值调整到Max(left,重复子字符串位置 + 1),因为窗口中如果包含该字符串则说明窗口中存在重复,需要收缩窗口的左边界
  4. 然后窗口不断的向右遍历到最后一个字符
  5. 为了快速查到是否为重复的字符串使用hashmap来记录,字符和字符位置,遇到相同字符的时候需要更新字符位置
class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 1. 设置变量记录最大值
        // 2. 遇到重复字符串的时候调整窗口边界
        // 3. 遍历处理到字符串的最右边
        // 4. 使用map记录字符串和字符串位置
        
	// 字符串长度 
        int len = s.length();
        int left = 0; // 左窗口
        int right = 0; // 右窗口 
        int max = 0; // 最长子串
	// 记录字符和字符位置
        Map<Character,Integer> charMap = new HashMap<>();
        while (right < len) {
            if(charMap.containsKey(s.charAt(right))) {
		// 这里使用Math.max是因为可能会发生新发现的重复字符在map中存储的位置在窗口最左边界外
                left = Math.max(left,charMap.get(s.charAt(right)) + 1);
            }
	    // 更新字符位置
            charMap.put(s.charAt(right), right);
            max = Math.max(max, right - left + 1);
            // 滑动右窗口
            right++;
        }

        return max;
    }
}

解法二就十分的简洁明了,好的算法好重要,效率上差距好大🥺

Q.E.D.


每一个平凡的日常都是连续的奇迹