滑动窗口 系列
滑动窗口是大部分是根据题目移动而去求一些特殊数据。
题目
1. 滑动窗口最大值
leetcode 239
第239题:滑动窗口最大值 |
---|
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。 |
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值所构成的数组。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
题目分析
先采用动态规划的理解的话
- dp[i] 是滑动到i位置时的最大值
- dp[i] = max(dp[i-k:i])
- 特殊情况时 i小于k时,取前i个最大值
- 返回dp[k-1:]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
n=len(nums)
dp=[0]*n
if n <=k:
return [max(nums)]
for i in range(n):
dp[i]=max(dp[i-k:i])
return dp[k-1:]
双端队列解决
- 新建一个双端队列,头部元素保持最大,
- 循环到下一个元素的时候,比较元素与队列末尾的元素,若末尾的元素大,则把队列里面的元素pop出去,依次比较。若小,则添加进队列
- 当队列头部元素等于i-k的时候,意味着队列头部元素已经不在k的范围内了,popleft。
- 当i >=k -1的时候证明滑动窗口启动了,需要往结果里面添加找到的最大元素。
维护一个双端队列,顶部元素最大,每次滑动取顶部元素添加进入。
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums:
return []
from collections import deque
dq = deque()
res = []
for i, num in enumerate(nums):
while dq and nums[dq[-1]] < num: # 当前数字比队列中的最大值还大,需要弹出
dq.pop()
dq.append(i) # 当前数字比队列中的最大值还小,需要放入
if dq[0] == i - k: # 当前数字是队列中的最大值,需要弹出
dq.popleft() # 弹出队列中的最大值
if i >= k - 1: # 当前数字是窗口中的最大值,需要放入
res.append(nums[dq[0]]) # 将队列中的最大值放入结果
return res
2. 无重复字符的最长字串
Leetcode 3
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
问题分析
维护一个窗口的长度(hash表,队列,dp,双指针,)如果遇到重复字段,就去计算目前的窗口的最大长度,并修改窗口的长度。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希表
# 时间复杂度: O(n)
# 空间复杂度: O(n)
if not s:
return 0
d = {}
max_len = 0
start = 0
for i, c in enumerate(s):
print(d, start, max_len)
if c in d and start <= d[c]: # 如果当前字符在哈希表中,并且当前字符的下标小于等于哈希表中的下标,则更新最大长度
start = d[c] + 1 # 更新下标
else: # 如果当前字符不在哈希表中,则更新最大长度
max_len = max(max_len, i - start + 1) # i - start + 1
d[c] = i
return max_len