滑动窗口
[1- 无重复字符的最长子串](#1- 无重复字符的最长子串)
[2- 找到字符串中所有字母异位词](#2- 找到字符串中所有字母异位词)
1- 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
var lengthOfLongestSubstring = function(s) {
// 无重复字符的连续的最长子串
// 滑动窗口:双指针+哈希表
let window = new Map()// 记录窗口内字符的最新索引(避免重复)
let left = 0
let maxLen = 0
for(let right = 0; right < s.length; right++){
const char = s[right]
// 如果当前字符已在窗口内(且索引≥left)
if(window.has(char) && window.get(char) >= left){
// 收缩左指针到「重复字符的下一位」
left = window.get(char) + 1
}
// 更新当前字符的最新索引
window.set(char,right)
// 更新最大长度(当前窗口长度 = right - left + 1)
maxLen = Math.max(maxLen,right-left+1)
}
return maxLen
};
2- 找到字符串中所有字母异位词
给定两个字符串 s 和 p,找到 s中所有 p的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
var findAnagrams = function(s, p) {
// 和最小覆盖子串很像,但这个子串长度是固定的
// 滑动窗口,双指针
let ans = []
let slen = s.length
let plen = p.length
let cnt = Array(128).fill(0)
let less = 0
// 如果s字符串比p字符串还短,直接返回ans
if(slen < plen) return ans
// 初始化p字符串对字符的需求
// less表示p字符串的字符个数
for(let char of p){
const code = char.charCodeAt(0)
if(cnt[code] === 0){
less++
}
cnt[code]++
}
let left = 0
for(let right = 0;right < slen; right++){
//
const rCode = s.charCodeAt(right)
cnt[rCode]--
if(cnt[rCode] === 0){
less--
}
// 固定滑动窗口大小为p字符串的长度
// 窗口区间[left,right]
if(right - left + 1 > plen){
const lCode = s.charCodeAt(left)
// 当前移除的字符是p字符串中需求的字符,需要将less-1
if(cnt[lCode] === 0){
less++
}
// 该字符需求+1
cnt[lCode]++
// 窗口右移
left++
}
// 该窗口正好是p的异位词子串
if(less === 0){
ans.push(left)
}
}
return ans
};