wuyijia

导航

数组章节的进阶54. 螺旋矩阵、904. 水果成篮、76. 最小覆盖子串、26. 删除有序数组中的重复项

54. 螺旋矩阵

 1 class Solution:
 2     def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
 3         m, n = len(matrix), len(matrix[0])
 4         res = [] #存放遍历后的结果
 5         startx = starty = 0
 6 
 7         for offset in range(min(m, n)//2): #offset初始值为0 左闭右开 range(1,1):不循环了
 8 
 9             for j in range(starty, n-offset-1): #从左到右
10                 res.append(matrix[startx][j])
11 
12             for i in range(startx, m-offset-1):#从上到下
13                 res.append(matrix[i][n-offset-1])
14 
15             for j in range(n-offset-1, starty,-1):#从右到左
16                 res.append(matrix[m-offset-1][j])
17 
18             for i in range(m-offset-1,startx, -1): #从下到上
19                 res.append(matrix[i][starty])
20             
21             startx += 1
22             starty += 1
23         
24         if min(m, n) % 2 == 1:
25             offset = min(m, n) // 2
26             if m <= n:
27                 for j in range(offset, n-offset):
28                     res.append(matrix[offset][j])
29             else:
30                 for i in range(offset, m-offset):
31                     res.append(matrix[i][n-offset-1])
32         
33         return res

 904. 水果成篮

滑动窗口+哈希表

 1 class Solution:
 2     def totalFruit(self, fruits: List[int]) -> int:
 3         #哈希表(键:树的种类,值:出现的次数)记录滑动窗口内的数,以及出现的次数
 4         cnt = Counter()
 5 
 6         left = 0 #滑动窗口的左边界
 7         ans = 0 #记录收集水果的最大数目
 8 
 9         #滑动窗口的右边界在循环里迭代器里赋予初值
10         for right, x in enumerate(fruits):
11             cnt[x] += 1
12             while len(cnt) > 2:
13                 cnt[fruits[left]] -= 1
14                 if cnt[fruits[left]] == 0:
15                     cnt.pop(fruits[left])
16                 left += 1
17             ans = max(ans, right-left+1)
18         
19         return ans

76. 最小覆盖子串

 滑动窗口+字典(哈希表)

 1 class Solution:
 2     def minWindow(self, s: str, t: str) -> str:
 3         #哈希表维护窗口内的字符
 4         need = collections.defaultdict(int)
 5         #遍历子字符串t存储在need中
 6         for i in t:
 7             need[i] += 1
 8         #记录一共需要多少字符,无需遍历哈希表(字典)
 9         needCnt  = len(t)
10         #初始化滑动窗口
11         res = (0, float('inf'))
12         i = 0
13 
14         for j, c in enumerate(s):
15             if need[c] > 0:
16                 needCnt -= 1
17             #need中的字符可为负,则说明滑动窗口内有多余的字符
18             need[c] -= 1
19             #滑动窗口包含了所有t的元素,但是有可能多包含了
20             if needCnt == 0:
21                 while True:
22                     c = s[i]
23                     if need[c] == 0:
24                         break
25                     need[c] += 1 #删除多余字符
26                     i += 1
27                 if j - i < res[1] - res[0]:
28                     #更新滑动窗口
29                     res = (i, j)
30                 #i增加一位,继续寻找满足条件的子串,直到j遍历完s
31                 need[s[i]] += 1
32                 needCnt += 1
33                 i += 1
34         
35         return '' if res[1] > len(s) else s[res[0]: res[1]+1]

 26. 删除有序数组中的重复项

快慢双指针

 1 class Solution:
 2     def removeDuplicates(self, nums: List[int]) -> int:
 3         #双指针
 4         s = 0
 5         f = 1
 6         while f < len(nums):
 7             if nums[s] != nums[f]:
 8                 s = s + 1
 9                 nums[s] = nums[f]
10             f += 1
11 
12         return s + 1

844. 比较含退格的字符串

匹配消除:栈;双指针

 1 class Solution:
 2     def backspaceCompare(self, s: str, t: str) -> bool:
 3         #从后向前双指针
 4         #同时从后向前遍历S和T(i初始为S末尾,j初始为T末尾),记录#的数量,模拟消除的操作,如果#用完了,就开始比较S[i]和S[j]。
 5         #如果S[i]和S[j]不相同返回false,如果有一个指针(i或者j)先走到的字符串头部位置,也返回false。空间:O(1)
 6         sSkipNum = tSkipNum = 0
 7         i = len(s) - 1
 8         j = len(t) - 1
 9         while True:
10             while i >= 0: #从后向前,消除S的#
11                 if s[i] == '#':
12                     sSkipNum += 1
13                 else:
14                     if sSkipNum > 0:
15                         sSkipNum -= 1
16                     else:
17                         break
18                 i -= 1
19             
20             while j >= 0: #从后向前,消除T的#
21                 if t[j] == '#':
22                     tSkipNum += 1
23                 else: 
24                     if tSkipNum > 0:
25                         tSkipNum -= 1
26                     else:
27                         break
28                 j -= 1
29             #后半部分#消除完了,接下来比较S[i] != T[j]
30             #S或者T遍历到头了
31             if i < 0 or j < 0:
32                 break #这有跳出循环的条件
33             if s[i] != t[j]:
34                 return False
35             #相同就同时往下减
36             i -= 1
37             j -= 1
38         
39         #说明S和T同时遍历完毕
40         if i == -1 and j == -1:
41             return True
42         return False

 

 

 
 
 
 
 

posted on 2023-08-27 21:19  小吴要努力  阅读(5)  评论(0编辑  收藏  举报