数组章节的进阶54. 螺旋矩阵、904. 水果成篮、76. 最小覆盖子串、26. 删除有序数组中的重复项
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
滑动窗口+哈希表
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
滑动窗口+字典(哈希表)
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]
快慢双指针
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
匹配消除:栈;双指针
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