滑动窗口问题分析
使用滑动窗口框架分析解答leetcode/力扣中经典的算法题。
滑动窗口的基础操作
# the iterable (list, str, ...) is "it"
# define a sliding window [left, right)
left = 0
right = 0
# define window states
wnd_state_1 = ...
wnd_state_2 = ...
...
# define target states
tgt_state_1 = ...
tgt_state_2 = ...
...
# define resulting state
result = ...
# expand window (moving right pointer)
expand_elem = it[right]
right += 1
# shrink window (moving left pointer)
shrink_elem = it[left]
left += 1
# define get_expand_condition() and get_shrink_condition()
# framework
while get_expand_condition() and right < len(it):
expand_elem = it[right]
right += 1
# update window states (expand) with expand_elem
while get_shrink_condition() and left <= right and left < len(it):
shrink_elem = it[left]
left += 1
# update window states (shrink) with shrink_elem
# update window states (expand) with expand_elem
# update resulting state
LC-3
给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。
分析:
窗口的状态应该是窗口内的字符的集合;
扩张条件是无条件地(True);
收缩条件是当前待加入窗口的字符已经在窗口的字符集合中出现了,需要收缩直到该字符不在窗口的字符集合里了;
扩张时更新窗口状态:字符加入集合;
收缩时更新窗口状态:从集合中删除字符;
def lengthOfLongestSubstring(self, s: str) -> int:
# define a sliding window [left, right)
left = 0
right = 0
# define window states
window = set()
# define resulting state
result = 0
# get_expand_condition() = True
while right < len(s):
# expand window (moving right pointer)
expand_elem = s[right]
right += 1
# get_shrink_condition() = expand_elem in window
while expand_elem in window and left <= right and left < len(s):
# shrink window (moving left pointer) with shrink_elem
shrink_elem = s[left]
left += 1
# update window states (shrink)
window.remove(shrink_elem)
# update window states (expand) with expand_elem
window.add(expand_elem)
# update resulting state
result = max(result, right - left)
return result
LC-438
给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词指由相同字母重排列形成的字符串(包括相同的字符串)。
分析:
窗口的状态是窗口内字符和计数;
目标状态是模式字符串p的字符和计数;
扩张条件是无条件地(True);
收缩条件是窗口的大小超过了给定模式字符串p的长度,由于right一次只会移动一格,所以该条件也一次只会移动一格;
扩张时更新窗口状态:将key的计数+1,如果没有则创建;
收缩时更新窗口状态:将key的计数-1,如果为0则删除;
def findAnagrams(self, s: str, p: str) -> List[int]:
string_length = len(s)
# define a sliding window [left, right)
left = 0
right = 0
# define window states
window_char_and_count = dict()
# define target states
target_char_and_count = dict()
for _ in p:
target_char_and_count[_] = target_char_and_count