Leetcode刷题——滑动窗口
这篇Blog将分享我自己在做Leetcode面试经典150题中滑动窗口部分几道题的思路,let’s go。
209.长度最小的子数组
题目
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的子数组 [$nums_l$, $nums_{l+1}$, …, $nums_{r - 1}$, $nums_r$] ,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 `[4,3]` 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
思路
- 第一个while循环中total不断累加end位置上的值
- 第二个循环判断total >= target,这时满足了条件中所说的大于等于
- 用ans来存储数组,并对其进行最小值比较
- total和start都后移,窗口滑动一位
提示:
这里的窗口并不是一成不变的,而是不断累加到满足条件,期间窗口可能包含一个两个三个数。
代码
1 |
|
时间复杂度
时间复杂度O(n),执行用时60ms,消耗内存26.9MB
3.无重复字符的最长字串
给定一个字符串 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
由英文字母、数字、符号和空格组成
思路
- 首先确定需要使用滑动窗口和哈希表
- 哈希表用于存储字符和其对应的索引
- 当字符已经存在于哈希表中,对应的滑动窗口左边界移到该字符存储于哈希表中的索引位置
- 涉及到四个初始变量。
n
表示s的长度,ans
用于存储结果,哈希表mp
,指针j
表示左边界
代码
1 |
|
时间复杂度
时间复杂度O(n),执行用时52ms,消耗内存16.5MB
30.串联所有单词的子串
给定一个字符串 s
和一个字符串数组 words
。 words
中所有字符串 长度相同。
s
中的 串联子串 是指一个包含 words
中所有字符串以任意顺序排列连接起来的子串。
- 例如,如果
words = ["ab","cd","ef"]
, 那么"abcdef"
,"abefcd"
,"cdabef"
,"cdefab"
,"efabcd"
, 和"efcdab"
都是串联子串。"acdbef"
不是串联子串,因为他不是任何words
排列的连接。
返回所有串联子串在 s
中的开始索引。你可以以 任意顺序 返回答案。
示例1:
输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:`[0,9]`
解释:
因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
示例2:
输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:`[]`
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。
示例 3:
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:`[6,9,12]`
解释:
因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。
提示:
1 <= s.length <= 104
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i]
和 s
由小写英文字母组成
思路
- 最开始初始化五个变量,
word_len
单词长度,total_len
单词长度之和,word_map
用Counter记录每个单词出现的次数,ans
用于存储结果 - 滑动窗口每次滑动一个单词长度,当我们窗口内的单词出现次数和原本的不匹配就移动右边界,直到窗口内单词计数不超过原始计数
代码
1 |
|
时间复杂度
时间复杂度O(n * m),执行时间72ms,消耗内存17.1MB
76 最小覆盖子串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于t
中该字符数量。 - 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。
提示:
m == s.length
n == t.length
1 <= m, n <= 105
s
和 t
由英文字母组成
思路
- 初始化五个变量,
need
用于记录t
每个字符的需求数量,missing
用于记录还需要匹配的字符数量,left
左边界,start
起始位置,min_len
长度,ans
存储结果 - 滑动窗口使用right指针遍历字符串
s
,如果当前字符在need
中数量大于0则减少missing
表示需求字符少一个 - 当
missing
为0即窗口内包含所有所需字符,移动left继续遍历直到need[s[left]]
不再小于 0。
代码
1 |
|
时间复杂度
时间复杂度O(n),执行用时108ms,消耗内存16.8MB
好的,滑动窗口部分的题目就四个,到这里就结束了。滑动窗口的核心思路就在于不断移动窗口去匹配题设所给出的条件,之前刷2024春招100题那会还没特别明白这部分,现在也是彻底会了🤣不过还是不想笔试或面试遇到,这个真的好烦。