给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
涉及知识点
滑动窗口
解决思路
最基本的固定滑动窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: deffindAnagrams(self, s: str, p: str) -> List[int]: ans=[] cnt_p=Counter(p) cnt_s=Counter() for right,c inenumerate(s): cnt_s[c]+=1 left=right-len(p)+1 if left<0: continue if cnt_s==cnt_p: ans.append(left) cnt_s[s[left]]-=1 return ans
560.和为K的子数组(中等)
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
涉及知识点
子串
解决思路
前缀和求解
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defsubarraySum(self, nums: List[int], k: int) -> int: s = [0] * (len(nums) + 1) for i, x inenumerate(nums): s[i + 1] = s[i] + x
ans = 0 cnt = defaultdict(int) for sj in s: ans += cnt[sj - k] cnt[sj] += 1 return ans
239.滑动窗口最大值(困难)
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
涉及知识点
子串
解决思路
双向单调队列求解
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]: ans=[] q=deque() for i,x inenumerate(nums): while q and nums[q[-1]]<=x: q.pop() q.append(i) if i-q[0]>=k: q.popleft() if i>=k-1: ans.append(nums[q[0]]) return ans
classSolution: defmerge(self, intervals: List[List[int]]) -> List[List[int]]: intervals.sort(key=lambda p: p[0]) # 按照左端点从小到大排序 ans = [] for p in intervals: if ans and p[0] <= ans[-1][1]: # 可以合并 ans[-1][1] = max(ans[-1][1], p[1]) # 更新右端点最大值 else: # 不相交,无法合并 ans.append(p) # 新的合并区间 return ans
189.轮转数组(中等)
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
涉及知识点
普通数组
解决思路
原地切片,注意要nums[:]
1 2 3 4 5 6 7 8 9 10 11
classSolution: defrotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """ n = len(nums) # 计算有效的次数 k = k%n # 原地切片即原地修改 nums[:] =nums[-k:]+ nums[0:-k]
for i inrange(n): if nums[i] <= 0or nums[i] >= max_len: nums[i] = 0 for i inrange(n): if nums[i] % max_len != 0: cur = (nums[i] % max_len) - 1 nums[cur] = (nums[cur] % max_len) + max_len for i inrange(n): if nums[i] < max_len: return i+1 return max_len
73.矩阵置零(中等)
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
涉及知识点
矩阵
解决思路
二次遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defsetZeroes(self, matrix: List[List[int]]) -> None: """ Do not return anything, modify matrix in-place instead. """ row = len(matrix) col = len(matrix[0]) row_zero = set() col_zero = set() for i inrange(row): for j inrange(col): if matrix[i][j] == 0: row_zero.add(i) col_zero.add(j) for i inrange(row): for j inrange(col): if i in row_zero or j in col_zero: matrix[i][j] = 0
54.螺旋矩阵(中等)
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
涉及知识点
矩阵
解决思路
可以根据转向来找规律,也可以直接标记遍历过的数进行判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
DIRS = (0, 1), (1, 0), (0, -1), (-1, 0) # 右下左上
classSolution: defspiralOrder(self, matrix: List[List[int]]) -> List[int]: m, n = len(matrix), len(matrix[0]) size = m * n ans = [] i, j, di = 0, -1, 0# 从 (0, -1) 开始 whilelen(ans) < size: dx, dy = DIRS[di] for _ inrange(n): # 走 n 步(注意 n 会减少) i += dx j += dy # 先走一步 ans.append(matrix[i][j]) # 再加入答案 di = (di + 1) % 4# 右转 90° n, m = m - 1, n # 减少后面的循环次数(步数) return ans