这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
滑动窗口类问题特点
- 计算过程与两端点表示的区间相关的称为滑动窗口。
- 默认固定大小的窗口,在一些条件触发的情况下,可能会将其大小进行修改。
- 滑动窗口本身并不是解决问题的一种方法(或者说算法),它其实就是问题本身。
- 滑动窗口一定是同向移动的。
- 滑动窗口是一类问题,不同的问题需要使用不同的算法和数据结构来解决。
题目
无重复字符的最长子串-3
描述:给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
类型:滑动窗口类问题。
示例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/lo…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
- 定义一个 map 数据结构存储 (k, v),其中 key 值为字符,value 值为前子串中下标对应的出现频率
- left,right 为窗口的左右边界
- 循环时,只要左边界小于总字符串长度(left < n),就可以一直向右滑
- 初始化的时候,滑动窗口的大小为0,(left=0)。因为窗口的右边界,要从字符串的第一位开始,所以初始化时(right = -1)
- 每次窗口滑动时只要不遇到重复的字符,窗口右边界+1,将改字符记录到map中
- 如果遇到重复的值了,也就是我们定义的map中已经纯在了(
!!freqMap[nextLetter]为true时),窗口向右移动一位,原先位置的字符出现频率设置为0。 - 取字串的长度
代码实现
/**
* @param {string} s
* @return {number}
*/
let lengthOfLongestSubstring = function (str) {
let n = str.length
// 滑动窗口为s[left...right]
let left = 0
let right = -1
let freqMap = {} // 记录当前子串中下标对应的出现频率
let max = 0 // 找到的满足条件子串的最长长度
while (left < n) {
let nextLetter = str[right + 1]
if (!freqMap[nextLetter] && nextLetter !== undefined) {
freqMap[nextLetter] = 1
right++
} else {
freqMap[str[left]] = 0
left++
}
max = Math.max(max, right - left + 1)
}
return max
}
示例分析
max 的变化
// 第 1 次循环
left = 0
right = 0
max = 1
map = {
p:1
}
//2
left = 0
right = 1
max = 2
map = {
p:1
w:1
}
//3
left = 1
right = 1
max = Math.max(2,1)
map = {
p:0
w:1
}
// 4
left = 2
right = 1
max = Math.max(2,0)
map = {
p:0
w:0
}
//5
left = 2
right = 1
max = Math.max(2,0)
map = {
p:0
w:0
}
//5 w
left = 2
right = 2
max = Math.max(2,1)
map = {
p:0
w:1
}
//6 k
left = 2
right = 3
max = Math.max(2,2)
map = {
p:0
w:1
k:1
}
//7 e
left = 2
right = 4
max = Math.max(2,3)
map = {
p:0
w:1
k:1
e:1
}
//8 w
left = 3
right = 4
max = Math.max(3,2)
map = {
p:0
w:0
k:1
e:1
}
//9 undefined
left = 4
right = 5
max = Math.max(3,2)
map = {
p:0
w:1
k:0
e:1
}
//10 undefined
left = 5
right = 5
max = Math.max(3,1)
map = {
p:0
w:1
k:0
e:0
}