《算法通关之路》学习笔记,记录一下自己的刷题过程,详细的内容请大家购买作者的书籍查阅。
力扣第239题
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
'''
方法一:暴力法(超时)
时间复杂度:O(nk)
空间复杂度:O(1)
'''
class Solution:
def maxSlidingWindow(self, nums: list[int], k: int) -> list[int]:
left, right = 0, k
res = []
while right <= len(nums):
res.append(max(nums[left: right]))
left, right = left + 1, right + 1
return res
nums, k = [1,3,-1,-3,5,3,6,7], 3
solu = Solution()
solu.maxSlidingWindow(nums, k)
'''
方法二:单调队列
时间复杂度:O(n)
空间复杂度:O(k)
'''
class Solution:
def maxSlidingWindow(self, nums: list[int], k: int) -> list[int]:
window = list()
res = list()
for i, n in enumerate(nums):
# 从尾部开始移除比新加入元素小的元素
while window and nums[window[-1]] < n:
window.pop()
# 将新加入的元素添加到window
window.append(i)
# 如果窗口外的元素仍然在window中,则将其移除
if window[0] == i-k:
window.pop(0)
# 将当前元素即当前最大元素对应数字放入结果数组
if i >= k - 1:
res.append(nums[window[0]])
return res
nums, k = [1,3,-1,-3,5,3,6,7], 3
solu = Solution()
solu.maxSlidingWindow(nums, k)
力扣第76题
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
'''
方法二:滑动窗口
'''
class Solution:
def minWindow(self, s: str, t: str) -> str:
max_window = s + 'a' # 最大窗口
t_dict = dict() # 哈希表记录t中的字符
# 统计t中的字符
for ch in t:
if not t_dict.get(ch):
t_dict[ch] = 0
t_dict[ch] += 1
# 判断当前窗口中是否包含全部t
def all_elem_zero() -> bool:
for key, _ in t_dict.items():
if t_dict[key] > 0:
return False
return True
left, right = 0, 0
while right < len(s):
if s[right] in t_dict:
t_dict[s[right]] -= 1
while all_elem_zero(): # 当前窗口包含全部t
while s[left] not in t_dict: # 缩小窗口时如果遇到不是t中的字符直接跳过
left += 1
if right -left + 1 < len(max_window): # 更新最小窗口值
max_window = s[left:right+1]
if s[left] in t_dict: # 之前减掉的值加回来
t_dict[s[left]] += 1
left += 1
right += 1
return "" if max_window == s + 'a' else max_window
s, t = "ADOBECODEBANC", "ABC"
solu = Solution()
solu.minWindow(s, t)
力扣第424题
给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。
在执行上述操作后,返回包含相同字母的最长子字符串的长度。
'''
方法一:滑动窗口
时间复杂度:O(n)
空间复杂度:O(1)
'''
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
max_len = 0
ch_cnt = dict() # 记录字符出现频率
left, right = 0, 0
while right < len(s):
if s[right] not in ch_cnt:
ch_cnt[s[right]] = 0
ch_cnt[s[right]] += 1
if max(ch_cnt.values()) + k < right - left + 1: # 频率最高的字符加上k比当前窗口小,则收缩左窗口
ch_cnt[s[left]] -= 1
left += 1
max_len = max(max_len, right-left+1) # 现在频率最高的字符加上k的长度与当前窗口相等或更大
right += 1
return max_len
s, k = "ABAB", 2
solu = Solution()
solu.characterReplacement(s, k)
'''
方法二:滑动窗口(避免每次求max)
时间复杂度:O(n)
空间复杂度:O(1)
'''
import collections
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
left = right = 0
max_char_n = 0
counts = collections.Counter()
for right in range(0, len(s)):
counts[s[right]] += 1
max_char_n = max(max_char_n, counts[s[right]])
if right - left + 1 > k + max_char_n:
counts[s[left]] -= 1
left += 1
return right - left + 1
s, k = "ABAB", 2
solu = Solution()
solu.characterReplacement(s, k)
'''
方法三:滑动窗口(更加工整的版本)
时间复杂度:O(n)
空间复杂度:O(1)
'''
import collections
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
max_char_n = res = 0
counts = collections.Counter()
for i in range(len(s)):
counts[s[i]] += 1
max_char_n = max(max_char_n, counts[s[i]])
if res - max_char_n < k:
res += 1
else:
counts[s[i-res]] -= 1
return res
s, k = "ABAB", 2
solu = Solution()
solu.characterReplacement(s, k)
力扣第567题
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
'''
方法一:滑动窗口
时间复杂度:O(n)
空间复杂度:O(1)
'''
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
ch_cnt = dict() # 统计字符频次的字典
for ch in s1:
if ch not in ch_cnt:
ch_cnt[ch] = 0
ch_cnt[ch] += 1
# 处理第一个窗口
for ch in s2[0: len(s1)]:
if ch in ch_cnt:
ch_cnt[ch] -= 1
if max(ch_cnt.values()) == 0:
return True
# 窗口向右移动
left, right = 0, len(s1)
while right < len(s2):
# 迁移至下一个窗口
if s2[left] in ch_cnt:
ch_cnt[s2[left]] += 1
if s2[right] in ch_cnt:
ch_cnt[s2[right]] -= 1
if max(ch_cnt.values()) == 0:
return True
left += 1
right += 1
return False
s1, s2 = "ab", "eidbaooo"
solu = Solution()
solu.checkInclusion(s1, s2)
笔记本-Github