3. Longest Substring Without Repeating Characters

给定一个字符串,求出其中最大的子串长度,子串中要求所有字符只出现一次。
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.

思路:
运用2个下标,一个遍历字符串,一个记录子串的起始位置,每次将遍历的字符与子串中的字符挨个比较,若当前字符与子串中有相等的,则更新子串的起始位置,每一次循环后,都比较当前的子串长度与之前的最大长度,若更大,则更新,否则不更新。

int lengthOfLongstSubstring(string s) {
    int res = 0, l = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        for (int j = l; j < i; j++) {
            if (s[i] == s[j]) {
                l = j + 1;
                break;
            }
        }
        res = i - l + 1 > res ? i - l + 1 : res;
    }
    return res;
}

 

Java 版(滑动窗口法):

  • 首先,判断当前字符是否包含在map中,如果不包含,将该字符添加到map(字符,字符在数组下标),此时没有出现重复的字符,左指针不需要变化。此时不重复子串的长度为:i-left+1,与原来的maxLen比较,取最大值;
  • 如果当前字符 ch 包含在 map中,此时有2类情况:
    1. 当前字符包含在当前有效的子段中,如:abca,当我们遍历到第二个a,当前有效最长子段是 abc,我们又遍历到 a, 那么此时更新 left 为 map.get(a)+1=1,当前有效子段更新为 bca ;
    2. 当前字符不包含在当前最长有效子段中,如:abba, 我们先添加a,b进map,此时left=0,我们再添加b,发现map中包含b,而且b包含在最长有效子段中, 就是1)的情况,我们更新 left=map.get(b)+1=2,此时子段更新为 b,而且map中任然包含a,map.get(a)=0;随后,我们遍历到a,发现a包含在map中,且map.get(a)=0,如果我们像1.一样处理,就会发现 left=map.get(a)+1=1,实际上,left此时 应该不变,left始终为2,子段变成 ba才对。
  为了处理以上2类情况,我们每次更新left,left=Math.max(left , map.get(ch)+1).另外,更新left后,不管原来的 s.charAt(i) 是否在最长子段中,我们都要将 s.charAt(i) 的位置更新为当前的i, 因此此时新的 s.charAt(i) 已经进入到 当前最长的子段中!

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> map = new HashMap<>();
        int res = 0, left = 0;
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            if(map.containsKey(c)){
                left = Math.max(left, map.get(c) + 1); //移动左边界
            }
            res = Math.max(res, i - left + 1); //与已有结果比较
            map.put(c, i); //更新下标
        }
        return res;
    }
}

 

posted @ 2020-05-15 17:27  星海寻梦233  阅读(98)  评论(0编辑  收藏  举报