解题思路
以字符串的每个字符为起始,找出不包含重复字符的最长子串
以字符串pwwkew为例,有如下情况:
- (pw)wkew
- pw(wke)w
可以看出规律:
- 依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的
- 假设选择字符串中的第left个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为right。那么,选择第left+1个字符作为起始位置时,首先从left+1 到right的字符同样不重复。
代码实现
var lengthOfLongestSubstring = function (s) {
if (s.length <= 1) {
return s.length;
}
let m = {};
let left = (right = maxLength = 0);
while (right < s.length) {
let c = s[right]; // current char
if (!(m[c] === undefined || m[c] < left)) {
left = m[c] + 1;
}
m[c] = right;
maxLength = Math.max(maxLength, right - left + 1);
right++;
}
return maxLength;
};
使用了类似滑动窗口的思想,用一个哈希表来记录每个字符最后一次出现的位置,然后使用左右指针来维护一个滑动窗口,保证窗口内的字符都是不重复的。当遇到重复字符时,将左指针移动到重复字符的下一个位置,保证窗口内的字符都是不重复的。同时,记录下窗口的最大长度,最后返回即可。
这个算法的时间复杂度是 O(n),其中 n 是字符串的长度。因为只需要遍历一遍字符串,所以时间复杂度是线性的。空间复杂度也是 O(n),因为需要使用一个哈希表来每个字符最后一次出现的位置