力扣-数组-滑动窗口

题目顺序

209长度最小的子数组,904水果成篮,76最小覆盖子串

ps:209,76找时间再做一遍

解题思路

1.滑动窗口求解的题目中,关键词为”求解连续“

2.暴力解法是双重for循环,相当于对滑动窗口的起始和终止点都遍历

3.滑动窗口求解是,只遍历终止点,当sum符合条件时,start++,向前一步缩小窗口

4.终止条件是终止点end遍历完

 

 

 1 class Solution(object):
 2     def minSubArrayLen(self, target, nums):
 3         """
 4         :type target: int
 5         :type nums: List[int]
 6         :rtype: int
 7         """
 8         # 暴力求解 时间复杂度是n方 容易超时
 9         # 采用滑动窗口(本质与双指针相似),因为寻找的是连续子数组所以可以滑动解决
10         i = 0
11         n = len(nums)
12         res = n+1
13         sumarr = 0
14         for j in range(n): # 只遍历窗口end
15             sumarr += nums[j]
16             while sumarr>=target: # 窗口和符合条件时,窗口start向前,缩短窗口
17                 res = min(res, j-i+1)
18                 sumarr -= nums[i]
19                 i += 1
20         if res==n+1:
21             return 0
22         else:
23             return res

# 本题是最小滑动窗口,所以当符合条件时,还要缩短窗口,start向前;不符合条件时,right向前遍历

 

 

 

 1 class Solution(object):
 2     def totalFruit(self, fruits):
 3         """
 4         :type fruits: List[int]
 5         :rtype: int
 6         """
 7         # 考虑用滑动窗口解决
 8         cnt = Counter() # 计数器,是字典的子类
 9         res = 0
10         left = 0
11         for right in range(len(fruits)):
12             # 往篮子里放
13             cnt[fruits[right]] += 1
14             while len(cnt)>2:
15                 # 篮子里多于两种水果,left向前
16                 # 篮子里最多有三种水果
17                 cnt[fruits[left]] -= 1
18                 if cnt[fruits[left]] == 0:# 当left指向的水果在篮子中没了
19                     cnt.pop(fruits[left]) # 删除篮子对left水果的计数
20                 left += 1
21             res = max(res, right-left+1)
22         
23         return res

# 本题是最大滑动窗口,当符合条件时,即篮子里有两种水果,求最大水果个数,然后right继续遍历;否则left向前直到符合条件,求最大水果个数,right继续遍历。

 

 

 

 1 class Solution(object):
 2     def minWindow(self, s, t):
 3         """
 4         :type s: str
 5         :type t: str
 6         :rtype: str
 7         """
 8         # 用字典和字典计数器辅助
 9         need = collections.defaultdict(int)
10         needcnt = len(t)
11         for tt in t:
12             need[tt] += 1
13         
14         # n = len(s)
15         res = s+'aaa'
16         left = 0
17         for j, ss in enumerate(s):
18             if need[ss]>0:
19                 needcnt -= 1
20             need[ss] -= 1
21             while needcnt==0:
22                 # 对于无关字符,直接跳过,left++
23                 while True:
24                     if need[s[left]]==0:# 说明是目标字符不可放弃,结束循环
25                         break
26                     need[s[left]] += 1  # 否则是无关字符,left向前
27                     left += 1
28                 # 更新结果
29                 if j-left+1<len(res):
30                     res = s[left:j+1]
31                 # 对于目标字符,判断是否可以向前,如果不能,窗口终点j++
32                 need[s[left]] +=  1
33                 needcnt += 1
34                 left += 1
35         if res==s+'aaa':
36             return ""
37         else: 
38             return res

# 本题思路:

最小覆盖子串——连续数组,考虑滑动窗口求解;

当滑动窗口符合覆盖目标字符串的要求时,移动left寻找最小覆盖长度;

当滑动窗口不符合覆盖目标字符串的要求时,移动j使其达到要求;

滑动窗口符合条件——如何移动left——当前left指向的是无关字符时,left就可以向前,此时更新res——当left指向的是目标字符时目标字符没有多余时,先更新res,然后寻找新的窗口终点j对应的滑动窗口。

 

posted @ 2023-04-04 12:39  Yalking  阅读(43)  评论(0)    收藏  举报