滑动窗口
问题一:求 A 中由 K 个不同整数组成的最长子数组的长度
right pointer 主动向前移动
left pointer 被动向前移动,为了保证[left,right]闭区间的合法性
from collections import Counter
def find(s,k):
n = len(s)
l,r = 0,0
cnt = Counter()
res = 0
count = 0
while r < n:
if cnt[s[r]] == 0:
count += 1
cnt[s[r]] += 1
while count > k:
cnt[s[l]] -= 1
if cnt[s[l]] == 0:
count -= 1
l += 1
res = max(res,r - l + 1)
r += 1
return res
问题二:A 中由最多 K 个不同整数组成的子数组的个数
这个和问题一是类似的,唯一不同的是,每一个合法的区间都会累加!
def find2(s,k):
n = len(s)
l,r = 0,0
cnt = Counter()
count = 0
res = 0
while r < n:
if cnt[s[r]] == 0:
count += 1
cnt[s[r]] += 1
while count > k:
cnt[s[l]] -= 1
if cnt[s[l]] == 0:
count -= 1
l += 1
res += r - l + 1
r += 1
return res
问题三:A中恰好由K个不同整数组成的子数组的个数
仔细思考一下,其实这个题就是find2(s,k) - find2(s,k - 1);
问题四:求A中能覆盖B的最小字串
这里用到了一个小技巧,那就是判断A中的字串是否包含B
通过一个哈希表与need变量记录,这确实比较巧妙!

def minWindow(self, s: str, t: str) -> str:
n,m = len(s),len(t)
if m > n:
return ""
cnt = Counter(t)
need = len(t)
l,r = 0,0
left,right = 0, -1
min_length = n + 1
while r < n:
cur_in = s[r]
if cnt[cur_in] > 0:
need -= 1
cnt[cur_in] -= 1
while need == 0:
cur_length = r - l + 1
if min_length > cur_length:
left,right = l,r
min_length = cur_length
cur_out = s[l]
if cnt[cur_out] == 0:
need += 1
cnt[cur_out] += 1
l += 1
r += 1
return s[left:right + 1]
问题五:【维护区间极差】

class Solution:
def minOperations(self, nums: List[int]) -> int:
n = len(nums)
nums = sorted(set(nums))
ans,left = 0,0
for right,x in enumerate(nums):
while nums[left] < x - n + 1:
left += 1
ans = max(ans,right - left + 1)
return n - ans

浙公网安备 33010602011771号