1.题目
2.思路
滑动窗口的思想:用双指针实现。
初步版本:用哈希表记录区间[i, j]之间不重复的数字,当出现重复数字之后,i ++, j = i.相当于每次重新new 一个哈希表来存储,这样其实有大量重复计算,最坏的可能是O(n * n),比如用例 abcdefa.
改进版本:首先只用一个哈希表,当出现重复数字后,删除map中第i个字符,如果发现还有重复数字,那么继续删。相当于这个滑动窗口,右边j 要加入,必须让左边的i挨个删除。
为什么在哈希表中是逐个删除是s[i]?而不是直接让i 移动到 和nums[j]相同的位置?
因为需要让位置i 到 跟nums[j]相同的位置j ‘中间的所有数字都从哈希表中删除。如果直接移动i 到j',那么哈希表中就依然还保存了区间外的数,这是不对的。在测试用例的时候也可以多测试几个特殊的,主要就是考虑各种边界条件。
全为空: “ ”
全都不等: “abcdef"
全部相等:”aaaaa"
连在一起的相等:“abbcd"
最后一个数才相等:”abcda"
还有就是自己随机输入很长的数:“asdhiasofhjdvf”
class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 0 ;
int n = s.length();
if(n == 0) return 0;
Map<Character, Integer>map = new HashMap();
int j = 0;
for(int i = 0 ; i < n; i++){
while(j < n && map.getOrDefault(s.charAt(j), - 1) == -1){
map.put(s.charAt(j), j);
j++;
}
ans = Math.max(ans, j - i);
if(j == n)break;
// 这一行非常关键!!!为什么是删除当前i的值?而不是直接把i移动到有重复数字的位置
map.remove(s.charAt(i));
}
return ans;
}
}
3.结果
4.感想
刷这题四五遍了,老是领悟不到滑动窗口的精髓。一边进,一边出,用map维持i - j 之间的数。知识就是不过脑子,感觉只有输出知识才能真正的记住知识。多动手,多动嘴!