思路
像这种求子串(而不是子序列,因为子序列不是连续的)的问题,应该先思考是否可以用滑动窗口
依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的,原因在于:假设我们选择字符串中的第 k 个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为 rk。那么当我们选择第 k+1 个字符作为起始位置时,首先从 k+1 到 rk 的字符显然是不重复的,并且由于少了原本的第 k 个字符,我们可以尝试继续增大 rk,直到右侧出现了重复字符为止。
因为满足上面这个性质,所以我们可以使用「滑动窗口」来解决这个问题。
代码
function lengthOfLongestSubstring(s: string): number {
if (!s.length) return 0;
if (s.length === 1) return 1;
let res = 0, l = 0, r = 1; // [l, r]滑动窗口
const curCharSet = new Set();
curCharSet.add(s[l]);
while (r < s.length) {
if (!curCharSet.has(s[r])) {
// 右指针往右延伸到最大子串
curCharSet.add(s[r]);
r = r + 1;
} else {
// 统计当前窗口大小
// console.log('l, r: ', l, r);
res = Math.max(res, r - l);
// 左指针滑动
curCharSet.delete(s[l]);
l = l + 1;
}
}
return Math.max(res, r - l);
}
const testStr = 'au';
console.log(lengthOfLongestSubstring(testStr));