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;
    }
}

恭喜你学习完成!✿

相关推荐
码农多耕地呗2 小时前
java字符串转Integer方法(正则表达式)
java·正则表达式
钓鱼的肝2 小时前
[GESP-4.2503.T2]二阶矩阵
c++·算法·矩阵
2301_800895102 小时前
BFS--备战蓝桥杯版h
算法·蓝桥杯·宽度优先
redcocal2 小时前
偏振光学——使用Lu-chipman极化分解算法分解米勒矩阵
算法·矩阵·偏振光学·极化分解·米勒矩阵·穆勒矩阵
小二·2 小时前
Go 语言系统编程与云原生开发实战(第39篇)
开发语言·云原生·golang
放下华子我只抽RuiKe52 小时前
机器学习全景指南-基石篇——预测连续值的线性回归
人工智能·深度学习·神经网络·算法·机器学习·自然语言处理·线性回归
笨笨马甲2 小时前
Qt的界面渲染体系
开发语言·qt
前端技术2 小时前
【鸿蒙实战】从零打造智能物联网家居控制系统:HarmonyOS Next分布式能力的完美诠释
java·前端·人工智能·分布式·物联网·前端框架·harmonyos
05大叔2 小时前
Mybatis-Plus
java·开发语言·mybatis