Leetcode Top100答案和解释 -- Python版本(矩阵)

73. 矩阵置零

python 复制代码
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        m, n = len(matrix), len(matrix[0])
        first_col_zero = False

        for i in range(m):
            if matrix[i][0] == 0:
                first_col_zero = True
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0

        for i in range(m - 1, -1, -1):
            for j in range(n - 1, 0, -1):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
            if first_col_zero:
                matrix[i][0] = 0
  1. 初步思路标题:标记数组法

    • 使用两个布尔数组分别记录需要置零的行和列

    • 需要O(m+n)额外空间,不符合常数空间的要求

  2. 原地标记优化思路

    • 利用矩阵的第一行和第一列作为标记位,记录对应行和列是否需要置零

    • 需要额外两个变量记录第一行和第一列本身是否包含0

    • 从右下角开始遍历修改,避免标记位被提前覆盖

  3. 关键策略优势

    • 空间复杂度优化到O(1),只使用常数个额外变量

    • 两次遍历即可完成标记和修改,时间复杂度O(m×n)

    • 通过逆序遍历避免标记位被覆盖导致的错误

  4. 具体实现

复制代码
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        m, n = len(matrix), len(matrix[0])
        first_col_zero = False  # 标记第一列是否需要置零

        # 第一次遍历:用第一行和第一列记录需要置零的行和列
        for i in range(m):
            # 检查第一列是否有0
            if matrix[i][0] == 0:
                first_col_zero = True
            # 从第二列开始检查
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0  # 标记第i行需要置零
                    matrix[0][j] = 0  # 标记第j列需要置零

        # 第二次遍历:根据标记置零(除第一行第一列外)
        for i in range(m - 1, -1, -1):
            # 从最后一列到第二列
            for j in range(n - 1, 0, -1):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
            # 最后处理第一列
            if first_col_zero:
                matrix[i][0] = 0

54. 螺旋矩阵

python 复制代码
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        dirs = [[0,1],[1,0],[0,-1],[-1,0]]
        m, n = len(matrix), len(matrix[0])
        ans = []
        i, j, di = 0, 0, 0
        for _ in range(m*n):
            ans.append(matrix[i][j])
            matrix[i][j] = None
            x, y = i + dirs[di][0], j + dirs[di][1]
            if x < 0 or x >= m or y < 0 or y >= n or matrix[x][y] is None:
                di = (di + 1) % 4
            i += dirs[di][0]
            j += dirs[di][1]
        
        return ans
  1. 初步思路标题:分层模拟法

    • 按层模拟,逐层遍历矩阵的外圈到内圈

    • 需要维护四个边界变量,处理边界收缩的逻辑较为复杂

  2. 方向数组+标记法优化思路

    • 使用方向数组表示四个移动方向(右、下、左、上)

    • 访问过的元素标记为None,遇到边界或已访问元素时改变方向

    • 通过取模运算循环切换方向,实现自动转向

  3. 关键策略优势

    • 代码简洁直观,避免复杂的边界判断和循环条件

    • 通过标记法自动处理转向逻辑,无需显式维护边界

    • 一次遍历即可完成,时间复杂度O(m×n)

  4. 具体实现

复制代码
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        # 方向数组:右、下、左、上
        dirs = [[0,1],[1,0],[0,-1],[-1,0]]
        m, n = len(matrix), len(matrix[0])
        ans = []
        i, j, di = 0, 0, 0  # 当前位置和方向索引
        
        for _ in range(m*n):
            ans.append(matrix[i][j])
            matrix[i][j] = None  # 标记已访问
            
            # 尝试按当前方向移动
            x, y = i + dirs[di][0], j + dirs[di][1]
            # 如果下一个位置越界或已访问,改变方向
            if x < 0 or x >= m or y < 0 or y >= n or matrix[x][y] is None:
                di = (di + 1) % 4  # 顺时针转向下一方向
            
            # 更新位置
            i += dirs[di][0]
            j += dirs[di][1]
        
        return ans

48. 旋转图像

python 复制代码
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)
        for i in range(n):
            for j in range(i, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        
        for row in matrix:
            row.reverse()
  1. 初步思路:直接模拟旋转

    • 最初可能想到创建一个新的矩阵,按照旋转规则将原矩阵的元素放到新矩阵的对应位置

    • 这种方法的时间复杂度为O(n²),但空间复杂度也为O(n²),不满足题目要求的原地修改条件

  2. 优化思路:两次操作转化法

    • 优化方向1:将复杂的旋转操作分解为两个简单的矩阵操作。顺时针旋转90度可以等价为先进行矩阵转置,然后对每一行进行反转

    • 优化方向2:利用矩阵转置(行列互换)和对换行内元素的组合,通过简单的元素交换实现旋转,避免了复杂的坐标计算

  3. 关键策略优势

    • 策略带来的具体好处1:原地操作,只使用常数级别的额外空间,完全满足题目要求

    • 策略带来的具体好处2:算法逻辑清晰简单,通过两个基础矩阵操作的组合,避免了复杂的元素移动计算

  4. 具体实现

复制代码
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)
        # 第一步:矩阵转置(沿主对角线翻转)
        # 只遍历上三角矩阵,将(i,j)与(j,i)交换
        for i in range(n):
            for j in range(i, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        
        # 第二步:每一行反转
        # 对转置后的矩阵的每一行进行左右翻转
        for row in matrix:
            row.reverse()

240. 搜索二维矩阵 II

python 复制代码
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        r, c = len(matrix), len(matrix[0])
        i, j = 0, c - 1

        while i < r and j >= 0:
            if matrix[i][j] > target:
                j -= 1
            elif matrix[i][j] < target:
                i += 1
            else:
                return True
        
        return False
  1. 初步思路标题(暴力遍历法)

    最直接的解法是对整个矩阵进行双重循环遍历,比较每个元素是否等于目标值。这种方法虽然简单直观,但时间复杂度为O(m×n),没有利用矩阵的有序特性,在矩阵规模较大时效率很低。

  2. 优化思路标题(Z字形搜索法)

    • 优化方向1:从矩阵的右上角(或左下角)开始搜索,利用矩阵的行列有序特性,每次比较可以排除一行或一列

    • 优化方向2:通过控制行索引和列索引的移动方向,实现线性时间复杂度的搜索,无需使用二分查找或额外空间

  3. 关键策略优势

    • 策略带来的具体好处1:每次比较都能排除一整行或一整列,搜索路径最多只经过m+n个元素,时间复杂度降为O(m+n)

    • 策略带来的具体好处2:仅使用两个指针变量,空间复杂度为O(1),且代码简洁易懂

  4. 具体实现

复制代码
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        # 获取矩阵的行数和列数
        r, c = len(matrix), len(matrix[0])
        # 从右上角开始搜索
        i, j = 0, c - 1

        # 当行索引在范围内且列索引在范围内时继续搜索
        while i < r and j >= 0:
            # 如果当前元素大于目标值,排除当前列
            if matrix[i][j] > target:
                j -= 1
            # 如果当前元素小于目标值,排除当前行
            elif matrix[i][j] < target:
                i += 1
            # 找到目标值
            else:
                return True
        
        # 搜索完所有可能位置仍未找到
        return False
相关推荐
无限进步_7 分钟前
【C++】巧用静态变量与构造函数:一种非常规的求和实现
开发语言·c++·git·算法·leetcode·github·visual studio
郝学胜-神的一滴17 分钟前
Socket实战:从单端聊天到多用户连接的实现秘籍
服务器·开发语言·python·网络协议·pycharm
zzwq.22 分钟前
线程池与进程池:concurrent.futures高效并发
python
Ricardo-Yang38 分钟前
SCNP语义分割边缘logits策略
数据结构·人工智能·python·深度学习·算法
凌波粒38 分钟前
LeetCode--344.反转字符串(字符串/双指针法)
算法·leetcode·职场和发展
啊哦呃咦唔鱼1 小时前
LeetCode hot100-543 二叉树的直径
算法·leetcode·职场和发展
soragui1 小时前
【Python】第 4 章:Python 数据结构实现
数据结构·windows·python
和小潘一起学AI1 小时前
CentOS 7安装Anaconda
开发语言·python
kcuwu.1 小时前
Python 正则表达式从入门到实战
数据库·python·正则表达式
不解不惑1 小时前
langchain qwen3 构建一个简单的对话系统
pytorch·python·langchain