LeetCode 热题 100 | 矩阵

**摘要:**本文解析 LeetCode 热题 100 中矩阵部分的题目。

矩阵

73 矩阵置零

核心逻辑: 通过两个布尔数组分别记录需要置零的行和列,先遍历矩阵标记所有含 0 的行和列,再根据标记结果分别对行、列批量置零,最终实现原地修改矩阵的目标(核心是 "标记 - 置零" 的分步逻辑)。


关键步骤:

  1. 初始化标记数组:创建两个布尔数组 rowZero(长度为矩阵行数 m)和 colZero(长度为矩阵列数 n),分别用于记录哪些行 / 列需要置零,初始值均为 false。

  2. 遍历标记行 / 列:逐行逐列遍历整个矩阵,若遇到元素 matrix[i][j] = 0,则将 rowZero[i] 设为 true(标记第 i 行需置零)、colZero[j] 设为 true(标记第 j 列需置零)。

  3. 置零标记行:遍历 rowZero 数组,若 rowZero[i] = true,则将矩阵第 i 行的所有元素置为 0。

  4. 置零标记列:遍历 colZero 数组,若 colZero[j] = true,则将矩阵第 j 列的所有元素置为 0。

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        boolean[] rowZero = new boolean[m]; // 记录哪些行需要置零
        boolean[] colZero = new boolean[n]; // 记录哪些列需要置零

        // 第一步:遍历矩阵,标记行/列
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    rowZero[i] = true;
                    colZero[j] = true;
                }
            }
        }

        // 第二步:置零标记的行
        for (int i = 0; i < m; i++) {
            if (rowZero[i]) {
                for (int j = 0; j < n; j++) {
                    matrix[i][j] = 0;
                }
            }
        }

        // 第三步:置零标记的列
        for (int j = 0; j < n; j++) {
            if (colZero[j]) {
                for (int i = 0; i < m; i++) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}

54 螺旋矩阵

核心逻辑: 通过边界收缩法控制螺旋的方向和范围 ------ 定义上、下、左、右四个边界,++按 "右→下→左→上" 的顺序循环遍历矩阵元素,每完成一个方向就收缩对应边界++,直到所有元素遍历完毕并收集到结果列表中。


关键步骤:

++初始化边界与结果++:

  1. 定义 top = 0、bottom = 矩阵行数 - 1、left = 0、right = 矩阵列数 - 1;

  2. 初始化空的结果列表 res(用于存储遍历后的元素)。

++循环遍历(边界收缩)++:

  1. 向右遍历:遍历 [left, right] 列,收集 top 行的所有元素到 res,完成后 top++(上边界下移);

  2. 向下遍历:遍历 [top, bottom] 行,收集 right 列的所有元素到 res,完成后 right--(右边界左移);

  3. 向左遍历(需判断上下边界是否交叉):若 top ≤ bottom,遍历 [right, left] 列,收集 bottom 行的所有元素到 res,完成后 bottom--(下边界上移);

  4. 向上遍历(需判断左右边界是否交叉):若 left ≤ right,遍历 [bottom, top] 行,收集 left 列的所有元素到 res,完成后 left++(左边界右移);

终止条件:当 top > bottom 或 left > right 时,所有元素遍历完毕,返回结果列表 res。

java 复制代码
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if (matrix == null || matrix.length == 0) return res;
        
        int top = 0, bottom = matrix.length - 1;
        int left = 0, right = matrix[0].length - 1;
        
        while (top <= bottom && left <= right) {
            // 向右遍历
            for (int j = left; j <= right; j++) {
                res.add(matrix[top][j]);
            }
            top++;
            
            // 向下遍历
            for (int i = top; i <= bottom; i++) {
                res.add(matrix[i][right]);
            }
            right--;
            
            // 向左遍历(判断边界)
            if (top <= bottom) {
                for (int j = right; j >= left; j--) {
                    res.add(matrix[bottom][j]);
                }
                bottom--;
            }
            
            // 向上遍历(判断边界)
            if (left <= right) {
                for (int i = bottom; i >= top; i--) {
                    res.add(matrix[i][left]);
                }
                left++;
            }
        }
        return res;
    }
}

48 旋转图像

**核心逻辑:**通过 "矩阵转置 + 每行左右翻转" 两步操作实现原地顺时针旋转 90 度 ------ 先将矩阵行和列互换完成转置,再对转置后的每一行进行左右翻转,无需额外矩阵空间,仅通过元素交换完成原地修改。


关键步骤:

  1. 转置矩阵:遍历矩阵上三角区域 (i 从 0 到 n-1,j 从 i 到 n-1),交换 matrix[i][j]matrix[j][i],完成后矩阵行和列互换;

  2. 翻转每行:遍历矩阵每一行(i 从 0 到 n-1),对当前行遍历前半部分列(j 从 0 到 n/2-1),交换 matrix[i][j]matrix[i][n-1-j],完成后该行元素左右翻转。

java 复制代码
public class RotateImage {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        
        // 第一步:转置矩阵
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                // 交换 matrix[i][j] 和 matrix[j][i]
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        
        // 第二步:对称交换
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n / 2; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][n - 1 - j];
                matrix[i][n - 1 - j] = temp;
            }
        }
    }
}

240 搜索二维矩阵 Ⅱ

**核心逻辑:**通过 "边界收缩法" 从矩阵右上角起始搜索 ------ 利用矩阵 "每行升序、每列升序" 的特性,以右上角为起始点,每次比较可排除一行或一列,逐步收缩搜索边界,无需额外空间且时间复杂度最优,高效判断。


关键步骤:

  1. 边界初始化:处理空矩阵边界情况(矩阵为 null / 行数为 0 / 列数为 0 时直接返回 false);定义行数 m = 矩阵长度、列数 n = 矩阵首行长度,初始化搜索起始点为矩阵右上角(row=0,col=n-1);

  2. 边界收缩搜索:循环判断 row <m 且 col>= 0(未越界),取当前位置值 current=matrix [row][col]:

    1. 若 current == target:找到目标值,直接返回 true;

    2. 若 current > target:当前列所有元素均大于目标值,左移列边界(col--)排除当前列;

    3. 若 current < target:当前行所有元素均小于目标值,下移行边界(row++)排除当前行;

  3. 终止返回:当循环因边界越界终止时,说明未找到目标值,返回 false。

java 复制代码
public class SearchMatrixII {
    public boolean searchMatrix(int[][] matrix, int target) {

        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {return false;}
        
        int m = matrix.length;    
        int n = matrix[0].length; 
        int row = 0;              
        int col = n - 1;          
        
        while (row < m && col >= 0) {
            int current = matrix[row][col];
            if (current == target) {
                return true;
            } else if (current > target) {
                col--;
            } else {
                row++;
            }
        }
        return false;
    }
}

恭喜你学习完成!✿

相关推荐
ictI CABL5 分钟前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀8 分钟前
DelayQueue 详解
java
jllllyuz20 分钟前
MATLAB 蒙特卡洛排队等待模拟程序
数据结构·matlab
自我意识的多元宇宙32 分钟前
树、森林——树、森林与二叉树的转换(森林转换为二叉树)
数据结构
敖正炀34 分钟前
PriorityBlockingQueue 详解
java
shark222222239 分钟前
Spring 的三种注入方式?
java·数据库·spring
海清河晏11141 分钟前
数据结构 | 双循环链表
数据结构·链表
workflower42 分钟前
机器人应用-楼宇室内巡逻
大数据·人工智能·算法·microsoft·机器人·动态规划·享元模式
ZPC82101 小时前
fanuc 机器人通过PR寄存器实现轨迹控制
人工智能·算法·计算机视觉·机器人
陈煜的博客1 小时前
idea 项目只编译不打包,跳过测试,快速开发
java·ide·intellij-idea