携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
题目描述:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解题思路:
以字符串 pwwkew 为例,找出从每一个字符开始的,不包含重复字符的最长子串,那么其中最长的那个字符串即为答案。对于该字符串,我们列举出以下结果:
以第一个字符 p 开始的最长字符串为 pw;
以第二个字符 w 开始的最长字符串为 w;
以第三个字符 w 开始的最长字符串为 wke;
以第四个字符 k 开始的最长字符串为 kew;
以第五个字符 e 开始的最长字符串为 ew;
以第六个字符 w 开始的最长字符串为 w;
根据以上的思路,可以应用滑动窗口思路解决该题。
滑动窗口其实是一个队列,比如示例中的 pwwkew 进入这个队列,字符为 pw 满足题目中要求的不含有重复字符,当再进入 w,队列变成了 pww,这时候不满足要求。所以,需要移动这个队列,把队列的左边的元素移出,直到满足要求,一直维持这样的队列,找出最长字符串
- 定义一个Set 对象,用来存储不重复的字符
- 定义滑动窗口的左右边界,让滑动窗口不断向前移动,当前字符不在set中,就加入set ,然后更新最大长度;当set中有重复字符时,不断让窗口左边界向右移动,并删除窗口之外的字符,直到滑动窗口内没有重复的字符,最后返回最大长度
var lengthOfLongestSubstring = function (s) {
const set = new Set(); //Set对象存储的值总是唯一的,用来判断滑动窗口内是否有重复元素
let right = 0,//滑动窗口右边界
left = 0,//滑动窗口左边界
maxLength = 0;
if (s.length === 0) {//极端情况
return 0;
}
for (right; right < s.length; right++) {
// has() 方法来判断value是否存在Set对象中
// 当前元素不在set中,就加入set,然后更新最大长度,右边界右移动一格继续下一轮循环
if (!set.has(s[right])) {
// add() 方法添加value到Set对象中
set.add(s[right]);
maxLength = Math.max(maxLength, set.size);
} else {
//set中有重复元素,左边界向右移动一格,并删除窗口之外的元素,直到滑动窗口内没有重复的元素
while (set.has(s[right])) {
//delete() 方法可以从一个 Set 对象中删除指定的元素。
set.delete(s[left]);
left++;
}
set.add(s[right]);//将s[right]加入set中
}
}
return maxLength;
};