跳到主要内容

3. [✔][M]无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

题解:

滑动窗口问题

双指针、快慢指针、hash map、滑动窗口。

滑动窗口问题,使用快慢指针,一前一后判断窗口扩大还是缩小。核心难点就在于窗口是扩大还是缩小的判断上。

/*
* @lc app=leetcode.cn id=3 lang=typescript
*
* [3] 无重复字符的最长子串
*/

// @lc code=start
function lengthOfLongestSubstring(s: string): number {
let win = new Map();//窗口字符计数器

let left = 0;//左指针
let right = 0;//右指针
let len = 0;//最长子串

while (right < s.length) {//没有到s末尾,一直执行循环
let c = s[right];//最右边字符
right++;//窗口扩大
win.set(c, (win.get(c) || 0) + 1);//窗口中增加一个right位置字符

while (win.get(c) > 1) {//窗口中已经有增加的字符了,继续循环,直到win中这个字符只有1次
let d = s[left];//left位置字符
left++;//窗口缩小
win.set(d, (win.get(d) || 0) - 1);//减掉1次字符数量
}

len = Math.max(len, right - left);//结果在最大值和当前计算的字符长度之间取最大值
}

return len;
};
// @lc code=end