1135 words
6 minutes
日拱两卒(九)
2026-08-10
20
旋转图像。
顺时针旋转90度。等价于沿副对角线对折,然后上下对折。
class Solution: def rotate(self, matrix: List[List[int]]) -> None: n, m = len(matrix), len(matrix[0]) for i in range(n): for j in range(n - 1 - i): matrix[i][j], matrix[n - 1 - j][n - 1 - i] = matrix[n - 1 - j][n - 1 - i], matrix[i][j]
for i in range(n // 2): for j in range(n): matrix[i][j], matrix[n - 1 - i][j] = matrix[n - 1 - i][j], matrix[i][j]19
螺旋矩阵。
螺旋顺序输出。
class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: ans = []
dx = [0, 1, 0, -1] dy = [1, 0, -1, 0] d = 0
x, y = 0, 0 cnt = 0 n, m = len(matrix), len(matrix[0]) visited = [[False for _ in range(m)] for _ in range(n)]
while cnt < n * m: ans.append(matrix[x][y]) cnt += 1 visited[x][y] = True tx, ty = x + dx[d], y + dy[d] if tx >= n or tx < 0 or ty >= m or ty < 0 or visited[tx][ty]: d = (d + 1) % 4 tx, ty = x + dx[d], y + dy[d] x, y = tx, ty
return ans18
矩阵置零。
如果一个元素为零,把它所在的一行和一列都变成零。
O(n + m)空间的做法很容易想到,记录每一行和每一列里是否有零。
这题的考察点很莫名其妙,题干说有无常数空间做法。
以为会有很巧妙的做法。
题解的方法也感觉没有很巧妙,就是把记录的东西放在每一行和每一列的第一个元素,再特殊处理第一行与第一列。
class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: n, m = len(matrix), len(matrix[0]) first_row_zero, first_col_zero = 0, 0 for j in range(m): first_row_zero = first_row_zero or not matrix[0][j] for i in range(n): first_col_zero = first_col_zero or not matrix[i][0] for i in range(1, n): for j in range(1, m): if not matrix[i][j]: matrix[0][j], matrix[i][0] = 0, 0 for i in range(1, n): for j in range(1, m): if not matrix[0][j] or not matrix[i][0]: matrix[i][j] = 0 if first_row_zero: for j in range(m): matrix[0][j] = 0 if first_col_zero: for row in matrix: row[0] = 017
缺失的第一个正数。
把每个数换到对应的位置,最多n个位置。
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: n = len(nums) for i in range(n): while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]: j = nums[i] - 1 nums[i], nums[j] = nums[j], nums[i]
for i in range(n): if nums[i] != i + 1: return i + 1
return n + 116
除了自身以外数组的乘积。
前缀积和后缀积。
class Solution: def productExceptSelf(self, nums: List[int]) -> List[int]: n = len(nums) pre = [1 for _ in range(n + 2)] suf = [1 for _ in range(n + 2)] for i in range(n): pre[i + 1] = pre[i] * nums[i] for i in range(n, 1, -1): suf[i] = suf[i + 1] * nums[i - 1] ans = [] for i in range(1, n + 1, 1): ans.append(pre[i - 1] * suf[i + 1]) return ans15
轮转数组。
向右K位。
class Solution: def rotate(self, nums: List[int], k: int) -> None: def reverse(l, r): i, j = l, r while i < j: nums[i], nums[j] = nums[j], nums[i] i += 1 j -= 1 n = len(nums) k %= n reverse(0, n - 1 - k) reverse(n - k, n - 1) reverse(0, n - 1)14
合并区间。
左端点排序完贪心。
class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: intervals.sort(key=lambda x : (x[0], x[1]))
ans = [] l, r = intervals[0][0], intervals[0][1] i = 1 n = len(intervals) while i < n: if intervals[i][0] > r: ans.append([l, r]) l, r = intervals[i][0], intervals[i][1] else: r = max(r, intervals[i][1]) i += 1 ans.append([l, r]) return ans13
最大子数组和。
数组里可能有负数。
把j那层循环优化成维护一个最小值。
class Solution: def maxSubArray(self, nums: List[int]) -> int: n = len(nums) s = [0 for _ in range(n + 1)] for i in range(n): s[i + 1] = s[i] + nums[i] pre_min = [1000000 for _ in range(n + 1)] pre_min[0] = s[0] ans = -1000000 for i in range(1, n + 1): ans = max(ans, s[i] - pre_min[i - 1]) pre_min[i] = min(pre_min[i - 1], s[i]) return ans12
最小覆盖子串。
返回最短的子串,包含目标串的所有字母。
滑动窗口维护每个字母的出现次数,右端点固定了以后左端点就可以贪心往右走。
Python要求字典里的Key得初始化才能用,很麻烦。
for i in range(26): cnt[i] = 0for i in range(32, 32 + 26): cnt[i] = 0如果直接用cnt = {}需要写这种初始化代码,用defaultdict(int)会默认有初始值0。
class Solution: def minWindow(self, s: str, t: str) -> str: ans = "" n = len(s) m = len(t)
target = defaultdict(int) for i in range(m): target[ord(t[i]) - ord('A')] += 1
# [l, r) l, r = 0, 0 cnt = defaultdict(int)
def check() -> bool: for c in target: if target[c] > cnt[c]: return False return True
while True: if r <= n - 1: r += 1 cnt[ord(s[r - 1]) - ord('A')] += 1 while check(): if r - l < len(ans) or ans == "": ans = s[l:r] cnt[ord(s[l]) - ord('A')] -= 1 l += 1 if r == n: break
return ans11
滑动窗口最大值。
单调队列。
class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: n = len(nums)
ans = [] q = deque() for r in range(n): l = r - k + 1 while q and q[0] < l: q.popleft() while q and nums[q[-1]] <= nums[r]: q.pop() q.append(r)
if l >= 0: ans.append(nums[q[0]])
return ans