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; } }