Leetcode 003: Longest Substring Without Repeating Characters

192 阅读2分钟

最长不重复的字串

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


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


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


解题思路:

  • 方法一:暴力求解遍历该字符串的所有字串。然后判断字串中是否含有重复的字符。该方法可以求出答案 但是运行速度真的太慢了。比如:S[i:j]表示 s字符串的i到j之间的字串。我们判断S[i:j]是否含有相同的字符。那么,当我们字串遍历到s[i+1:j] s[i+1:j+1] s[i:j+1] 等情况时候。我们会发现子字符串 s[i-1:j-1] 的子字符串被重复判断了多次。由此 我们考虑第二种方法 ☟
  • 方法二:最理想的情况: 当我们判断s[i:j+1]是否有重复字符时 只需要判断s[j:j+1] 是否是 s[i:j]的字串即可。因为我们s[i:j]已经判断过了。 这样 本题目就转化为一个判断区间内的字符是否重复。 维护好这个区间即可。 滑动窗口即是本题的解决方案
    解题步骤:定义两个变量left、right代表窗口的左右位置。用一个set来存当前窗口内的字符。当新来一个字符时:判断该字符是否已经在窗口中出现。如果出现:缩小窗口,移除窗口左值。加入窗口右值。 如果没有出现:扩大窗口,加入新来的字符。计算当前的窗口值并和旧窗口值取最值。将窗口的右边的值+1。 废话不多说 直接上代码
public int lengthOfLongestSubstring(String s) {
        int ans = 0;
        Set<Character> set = new HashSet<>();
        int left = 0;  // 窗口左值
        int right = 0; // 窗口右值
        int len = s.length();
        while (left < len && right < len){ 
            if(!set.contains(s.charAt(right))){
                set.add(s.charAt(right++));
                ans = Math.max(ans,right - left);
            }else {
                set.remove(s.charAt(left ++));
            }
        }
        return ans;
    }

总结: 滑动窗口的思想是在编程题中经常遇到的一种解决方案。特别在遍历求值的题目中。暴力美学固然有效。但同时要考虑时间复杂度和空间复杂度。减少重复遍历。