題目:
3. 無重復字符的最長子串
解法:
思想, 使用滑動窗口, 下標 i 表示左邊界, 下標 j 表示右邊界. i 和 j 之間的長度是不重復的子串的長度.
j 一步一步的走, 用一個HashMap存儲j走過的元素(元素 --> 下標).
對于i來說, 只有當出現(xiàn)重復元素的時候才需要更新. 當重復的時候, 取重復位置的最大下標+1. 但是我們不刪除過往的元素, 也就是說過期的元素依然會存在于HashMap中, 這時候我們就直接取 (重復元素的下標+1) 和 當前位置的最大值.
然后每輪結束的時候計算一次長度, 和之前的相比取最大.
流程為:
==> j 往右邊走;
==> 遇到重復元素, i 需要是否需要更新, 取決于重復元素是否過期(也就是重復的元素的下標比 i 的小, 就不更新 i ) ;
把 j 位置的元素壓入HashMap;
計算長度, 和歷史相比取最長;
直到結束.
public int lengthOfLongestSubstring(String s) {
// 滑動窗口, 用 HashMap判斷重復
Map<Character, Integer> map = new HashMap<>();
int res = 0;
for (int i = 0, j = 0; j < s.length(); j++) {
// 當前j位置的字符
char ch = s.charAt(j);
if (map.containsKey(ch)) {
i = Math.max(map.get(ch) + 1, i);
}
map.put(ch, j);
res = Math.max(res, j - i + 1);
}
return res;
}
可以使用數(shù)組優(yōu)化Hashmap
public int lengthOfLongestSubstring(String s) {
// 使用數(shù)組優(yōu)化HashMap, 把數(shù)組看作是特殊的Hashmap
int[] map = new int[128];
int res = 0;
for (int i = 0, j = 0; j < s.length(); j++) {
char ch = s.charAt(j);
// 每次都取最大的i, 因為index比i小的元素被認為是過期的, 無效的
i = Math.max(map[ch], i);
// 每次都put
map[ch] = j + 1;
// 計算總長
res = Math.max(res, j - i + 1);
}
return res;
}