当前位置: 首页 > news >正文

【LeetCode Hot100 矩阵】矩阵置零、螺旋矩阵、旋转图像、搜索二维矩阵II

矩阵

    • 1. 矩阵置零(Set Matrix Zeroes)
      • 解题思路
        • 步骤:
      • 代码实现
    • 2. 螺旋矩阵(Spiral Matrix)
      • 解题思路
        • 具体步骤:
      • 代码实现
    • 3. 旋转矩阵 90 度
      • 解决思路
      • 代码实现
    • 5. 搜索二维矩阵中的目标值
      • 解决思路
      • 代码实现

1. 矩阵置零(Set Matrix Zeroes)

给定一个 m x n 的矩阵 matrix,如果一个元素是 0,则将其所在的整行和整列都设置为 0。你需要 原地 修改输入矩阵,不能 使用额外的矩阵。

解题思路

要实现原地修改矩阵,可以借助矩阵的第一行和第一列作为辅助存储,记录哪些行和列需要被置零。

步骤:
  1. 检查第一行和第一列是否包含零

    • 由于我们使用第一行和第一列来标记其他行列是否需要置零,所以需要先检查第一行和第一列是否包含零。如果包含零,我们分别用 rowFlagcolFlag 进行标记。
  2. 遍历矩阵

    • 从第二行第二列开始遍历整个矩阵。如果某个元素是零,则将其所在的第一行和第一列对应的元素设为零,表示该行和该列后续需要置零。
  3. 根据标记置零

    • 再次遍历矩阵,根据第一行和第一列的标记,将需要置零的位置修改为零。
  4. 处理第一行和第一列

    • 最后,根据 rowFlagcolFlag 的值,单独处理第一行和第一列的置零问题。

代码实现

class Solution {
    public void setZeroes(int[][] matrix) {
        int n = matrix[0].length;  // 列数
        int m = matrix.length;     // 行数
        boolean colFlag = false, rowFlag = false;

        // 检查第一列是否包含零
        for (int i = 0; i < m; i++) {
            if (matrix[i][0] == 0) {
                colFlag = true;
                break;
            }
        }

        // 检查第一行是否包含零
        for (int j = 0; j < n; j++) {
            if (matrix[0][j] == 0) {
                rowFlag = true;
                break;
            }
        }

        // 遍历矩阵,使用第一行和第一列标记零的位置
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][j] == 0) {
                    matrix[0][j] = 0;  // 标记该列
                    matrix[i][0] = 0;  // 标记该行
                }
            }
        }

        // 根据第一行和第一列的标记进行置零
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[0][j] == 0 || matrix[i][0] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }

        // 处理第一列置零
        if (colFlag) {
            for (int i = 0; i < m; i++) {
                matrix[i][0] = 0;
            }
        }

        // 处理第一行置零
        if (rowFlag) {
            for (int j = 0; j < n; j++) {
                matrix[0][j] = 0;
            }
        }
    }
}

2. 螺旋矩阵(Spiral Matrix)

给定一个 m x n 的矩阵,按螺旋顺序返回矩阵中的所有元素。

解题思路

我们可以模拟螺旋遍历的过程,使用四个边界来控制当前遍历的范围。随着遍历的进行,逐步缩小这些边界,直到遍历完成整个矩阵。

具体步骤:
  1. 定义边界

    • l 表示左边界,初始为 0。
    • r 表示右边界,初始为 m-1
    • t 表示上边界,初始为 0。
    • b 表示下边界,初始为 n-1
  2. 遍历顺序

    • 按照螺旋顺序:从左到右遍历上边界,向下遍历右边界,从右到左遍历下边界,向上遍历左边界。
    • 每次遍历完一条边后,更新相应的边界。
  3. 终止条件

    • 当结果列表的大小等于 m * n 时,遍历结束。

代码实现

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> list = new ArrayList<>();
        int m = matrix[0].length, n = matrix.length;
        int l = 0, r = m - 1, t = 0, b = n - 1;
        
        // 继续遍历直到所有元素都被加入列表
        while (list.size() < m * n) {
            // 从左到右遍历上边界
            for (int i = l; i <= r; i++) {
                if (list.size() == m * n) break;
                list.add(matrix[t][i]);
            }
            t++;  // 缩小上边界的范围

            // 从上到下遍历右边界
            for (int i = t; i <= b; i++) {
                if (list.size() == m * n) break;
                list.add(matrix[i][r]);
            }
            r--;  // 缩小右边界的范围

            // 从右到左遍历下边界
            for (int i = r; i >= l; i--) {
                if (list.size() == m * n) break;
                list.add(matrix[b][i]);
            }
            b--;  // 缩小下边界的范围

            // 从下到上遍历左边界
            for (int i = b; i >= t; i--) {
                if (list.size() == m * n) break;
                list.add(matrix[i][l]);
            }
            l++;  // 缩小左边界的范围
        }

        return list;
    }
}

3. 旋转矩阵 90 度

给定一个 n x n 的二维矩阵,编写一个函数将该矩阵顺时针旋转 90 度。你必须在原地(即不使用额外的二维数组)完成旋转。

解决思路

该问题可以通过两步操作实现:

  1. 水平翻转:将矩阵上下翻转。
  2. 对角线翻转:再将矩阵沿主对角线进行翻转。

通过这两步操作,我们可以原地完成矩阵的 90 度顺时针旋转。

代码实现

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        // 先水平翻转
        for(int i = 0; i < n/2; i++) {
            for(int j = 0; j < n; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n-i-1][j];
                matrix[n-i-1][j] = temp;
            }
        }
        // 再沿着对角线翻转
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < i; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
}

5. 搜索二维矩阵中的目标值

给定一个 m x n 的矩阵 matrix 和一个目标值 target,编写一个函数判断目标值是否在矩阵中。矩阵中的元素按照以下规则排序:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

你需要在 O(m + n) 时间复杂度内完成这个搜索。

解决思路

由于矩阵的元素是按行升序、按列升序排列的,我们可以使用一种特殊的搜索方法:

  1. 从矩阵的右上角开始搜索:

    • 如果当前元素等于目标值,直接返回 true
    • 如果当前元素大于目标值,说明目标值可能在该元素的左边(向左移动一列)。
    • 如果当前元素小于目标值,说明目标值可能在该元素的下方(向下移动一行)。
  2. 这样,每次搜索都可以排除一行或一列,因此我们可以在 O(m + n) 时间复杂度内完成搜索。

代码实现

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        int x = 0, y = n - 1;  // 从右上角开始搜索
        while (x < m && y >= 0) {  // 当索引仍在矩阵范围内
            if (matrix[x][y] == target) {
                return true;  // 找到目标值
            } else if (matrix[x][y] > target) {
                y--;  // 当前值大于目标值,向左移动
            } else {
                x++;  // 当前值小于目标值,向下移动
            }
        }
        return false;  // 未找到目标值
    }
}

相关文章:

  • 开源协议深度解析:理解MIT、GPL、Apache等常见许可证
  • JavaScript 简介
  • 枚举类型Enum
  • DeepSeek-R1 + Cherry Studio 本地部署打造个人 AI 知识库
  • C语言01
  • Kimi k1.5:继Deepseek R1 后多模态 AI 的新标杆
  • 低成本、高效率且成熟的电商实时数据采集方案:梦想成真?
  • 放大镜效果
  • 图论算法篇:邻接矩阵以及邻接表和链式前向星建图
  • winfrom实现人脸识别比对功能
  • 大模型开发实战篇5:多模态--文生图模型API
  • 如何设置Python爬虫的User-Agent?
  • torch-xla动态shape——通过torch.nonzero分析mhlo实现
  • 第六天:requests库的用法
  • JS数组扁平化
  • Java与Go相比,有什么独特的优势
  • Openshift或者K8S上部署xxl-job
  • 电商分布式场景中如何保证数据库与缓存的一致性?实战方案与Java代码详解
  • vtkCamera类的Dolly函数作用及相机拉近拉远
  • 【力扣】199.二叉树的右视图
  • 央视315晚会曝光“保水虾仁”后,湛江4家涉事企业被罚超800万元
  • 纪念|“补白大王”郑逸梅,从藏扇看其眼光品味
  • 巴基斯坦军方:印度向巴本土及巴控克什米尔发射导弹
  • 茹诗瑶评《失去伊斯坦布尔》︱“帝国主义者”的多重面相
  • 黄道炫:南京102天——黄镇球的防空日记
  • 特朗普:不谋求第三个总统任期,中意万斯鲁比奥“接棒”