力扣top100(day01-05)--矩阵

73. 矩阵置零

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int length=matrix.length;
        int wingth=matrix[0].length;
        // 使用集合记录需要置零的行和列
        Set<Integer> n = new HashSet<>();
        Set<Integer> m = new HashSet<>();
        for(int i=0;i<length;i++){
            for(int j=0;j<wingth;j++){
                if(matrix[i][j]==0){
                    n.add(i);
                    m.add(j);
                }
            }
        } 
        for(int l:n){
            for(int k=0;k<wingth;k++){
                matrix[l][k]=0;
            }
        }
        for(int g:m){
            for(int h=0;h<length;h++){
                matrix[h][g]=0;
            }
        }
    }
}

代码解读:矩阵置零(Set Matrix Zeroes)

这段代码实现了将矩阵中所有0元素所在的行和列全部置为0的功能。以下是详细解析:


1. 核心思路
  • 问题要求:给定一个m×n的矩阵,如果某个元素为0,则将其所在行和列的所有元素都设为0。

  • 解决方法:使用两个HashSet分别记录需要置零的行和列索引,然后统一处理。


2. 代码解析
(1) 初始化行列集合

java

复制代码
Set<Integer> n = new HashSet<>();  // 存储需要置零的行索引
Set<Integer> m = new HashSet<>();  // 存储需要置零的列索引
  • n:记录包含0元素的行号

  • m:记录包含0元素的列号

(2) 第一次遍历:标记0的位置

java

复制代码
for(int i=0;i<length;i++){
    for(int j=0;j<wingth;j++){
        if(matrix[i][j]==0){
            n.add(i);  // 记录行号
            m.add(j);  // 记录列号
        }
    }
}
  • 遍历整个矩阵,发现0时记录其行列索引。
(3) 行置零处理

java

复制代码
for(int l:n){
    for(int k=0;k<wingth;k++){
        matrix[l][k]=0;  // 将整行置零
    }
}
  • 遍历所有标记行,将该行所有元素设为0。
(4) 列置零处理

java

复制代码
for(int g:m){
    for(int h=0;h<length;h++){
        matrix[h][g]=0;  // 将整列置零
    }
}
  • 遍历所有标记列,将该列所有元素设为0。

3. 复杂度分析
  • 时间复杂度:O(m×n),需要遍历矩阵两次(标记+置零)

  • 空间复杂度:O(m+n),最坏情况下需要存储所有行和列索引


4. 示例演示

输入矩阵

text

复制代码
[
  [1, 1, 1],
  [1, 0, 1],
  [1, 1, 1]
]

执行过程

  1. 发现0在(1,1),记录行1和列1

  2. 将第1行全部置零:[1,0,1]→[0,0,0]

  3. 将第1列全部置零:

    • [1][0]→0

    • [2][0]→0(实际值不变)

  4. 输出

text

复制代码
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

54. 螺旋矩阵

java 复制代码
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order = new ArrayList<Integer>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return order;
        }
        int rows = matrix.length, columns = matrix[0].length;
        int left = 0, right = columns - 1;
        int top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            // 1. 从左到右遍历上层
            for (int column = left; column <= right; column++) {
                order.add(matrix[top][column]);
            }
            // 2. 从上到下遍历右列
            for (int row = top + 1; row <= bottom; row++) {
                order.add(matrix[row][right]);
            }
            // 3. 从右到左遍历下层(确保不是单行)
            if (left < right && top < bottom) {
                for (int column = right - 1; column > left; column--) {
                    order.add(matrix[bottom][column]);
                }
                // 4. 从下到上遍历左列(确保不是单列)
                for (int row = bottom; row > top; row--) {
                    order.add(matrix[row][left]);
                }
            }
            // 边界收缩
            left++; right--; top++; bottom--;
        }
        return order;
    }
}

代码解读:螺旋矩阵(Spiral Matrix)

这段代码实现了按顺时针螺旋顺序遍历二维矩阵的功能。以下是详细解析:


1. 核心思路
  • 问题要求:将矩阵元素按从外到内顺时针顺序排列。

  • 解决方法 :使用边界收缩法,通过四个边界指针(left, right, top, bottom)逐步向内层遍历。


2. 代码解析
(1) 初始化边界指针

java

复制代码
int left = 0, right = columns - 1;  // 左右边界(列)
int top = 0, bottom = rows - 1;     // 上下边界(行)
  • left/right控制列范围,top/bottom控制行范围。
(2) 螺旋遍历

java

复制代码
while (left <= right && top <= bottom) {
    // 1. 从左到右遍历上层
    for (int column = left; column <= right; column++) {
        order.add(matrix[top][column]);
    }
    // 2. 从上到下遍历右列
    for (int row = top + 1; row <= bottom; row++) {
        order.add(matrix[row][right]);
    }
    // 3. 从右到左遍历下层(确保不是单行)
    if (left < right && top < bottom) {
        for (int column = right - 1; column > left; column--) {
            order.add(matrix[bottom][column]);
        }
        // 4. 从下到上遍历左列(确保不是单列)
        for (int row = bottom; row > top; row--) {
            order.add(matrix[row][left]);
        }
    }
    // 边界收缩
    left++; right--; top++; bottom--;
}

遍历顺序

  1. 左到右(上层)

  2. 上到下(右列)

  3. 右到左(下层,需判断非单行)

  4. 下到上(左列,需判断非单列)

(3) 边界收缩

每次完成一圈遍历后,四个边界同时向内收缩:

java

复制代码
left++;   // 左边界右移
right--;  // 右边界左移
top++;    // 上边界下移
bottom--; // 下边界上移

3. 示例演示

输入矩阵

text

复制代码
[
 [1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]
]

执行过程

  1. 第一圈:

    • → 1→2→3

    • ↓ 6→9

    • ← 8→7

    • ↑ 4

    • 边界收缩:left=1, right=1, top=1, bottom=1

  2. 第二圈:

    • → 5

    • 边界收缩结束

  3. 输出[1,2,3,6,9,8,7,4,5]


4. 复杂度分析
  • 时间复杂度:O(m×n),每个元素被访问一次

  • 空间复杂度:O(1)(不考虑输出列表)


5. 关键点总结
  1. 边界条件

    • 检查top < bottomleft < right避免重复遍历单行/列

    • 空矩阵直接返回

  2. 遍历顺序

    • 必须遵循→↓←↑的严格顺序
  3. 终止条件

    • left > righttop > bottom时结束循环

48. 旋转图像

java 复制代码
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 + 1) / 2; ++j) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = temp;
            }
        }
    }
}

代码解读:螺旋矩阵(Spiral Matrix)

1. 获取矩阵维度

java

复制代码
int n = matrix.length;
  • 作用:获取n×n矩阵的边长

  • 示例 :3×3矩阵 → n=3

2. 外层循环:控制旋转层数

java

复制代码
for (int i = 0; i < n / 2; ++i) {
  • 含义

    • n / 2:矩阵需要旋转的层数(如4×4矩阵有2层)

    • i:当前处理的层数索引(从外到内)

  • 示例

    • 4×4矩阵:i取值0,1(两层)

    • 3×3矩阵:i取值0(一层,中心点不动)

3. 内层循环:处理当前层元素

java

复制代码
for (int j = 0; j < (n + 1) / 2; ++j) {
  • 含义

    • (n + 1) / 2:处理奇偶矩阵差异

    • j:当前层元素的列索引

  • 设计原因

    • 奇数矩阵:中间列不需要处理(如3×3矩阵的j取值0,1)

    • 偶数矩阵:全部列都需要处理

4. 四元素轮换核心逻辑

java

复制代码
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;

分步解析(以3×3矩阵的(0,0)点为例):

  1. 保存左上角

    java

    复制代码
    int temp = matrix[0][0]; // temp = 1
  2. 左下 → 左上

    java

    复制代码
    matrix[0][0] = matrix[2][0]; // 1 ← 7
  3. 右下 → 左下

    java

    复制代码
    matrix[2][0] = matrix[2][2]; // 7 ← 9
  4. 右上 → 右下

    java

    复制代码
    matrix[2][2] = matrix[0][2]; // 9 ← 3
  5. temp → 右上

    java

    复制代码
    matrix[0][2] = temp; // 3 ← 1

坐标变换规律

位置 坐标变换公式 示例(3×3)
左上 (i,j) (0,0)
左下 (n-j-1,i) (2,0)
右下 (n-i-1,n-j-1) (2,2)
右上 (j,n-i-1) (0,2)
5. 边界处理细节
  • 奇数矩阵中心点

    • n为奇数时,(n + 1) / 2确保中心点不被处理

    • 例如3×3矩阵的中心点(1,1)不会被遍历到

6. 时间复杂度分析
  • O(n²):每个元素被访问一次

  • 空间复杂度O(1) :仅使用temp临时变量

7. 示例完整流程

输入矩阵

text

复制代码
[
 [1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]
]

旋转步骤

  1. 外层(0,0)点开始:

    • 四角交换:1←7←9←3←1

    • 边中交换:2←4←8←6←2

  2. 结果:

text

复制代码
[
 [7, 4, 1],
 [8, 5, 2],
 [9, 6, 3]
]
8. 关键设计思想
  1. 分层处理:将矩阵看作洋葱,逐层剥离

  2. 四元组交换:每组4个位置同时旋转

  3. 坐标映射:通过数学计算确定旋转后的位置

  4. 奇偶兼容(n+1)/2的统一处理

9. 常见误区提醒
  1. 边界错误

    • 错误:使用j < n / 2会漏掉奇数列

    • 正确:必须用(n + 1) / 2

  2. 交换顺序

    • 必须逆时针或顺时针统一方向
  3. 中心点处理

    • 奇数矩阵中心点无需旋转

240. 搜索二维矩阵 II

java 复制代码
class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        for (int[] row : matrix) {
            for (int element : row) {
                if (element == target) {
                    return true;
                }
            }
        }
        return false;
    }
}
java 复制代码
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;
            }
            if (matrix[x][y] > target) {
                --y;
            } else {
                ++x;
            }
        }
        return false;
    }
}
相关推荐
☆璇7 分钟前
【C++】哈希的应用:位图和布隆过滤器
算法·哈希算法
一株月见草哇2 小时前
Matlab(4)
人工智能·算法·matlab
hans汉斯2 小时前
基于深度学习的苹果品质智能检测算法研究
人工智能·深度学习·算法
mit6.8242 小时前
[Robotics_py] 机器人运动模型 | `update`函数 | 微积分&矩阵
人工智能·python·算法
地平线开发者3 小时前
征程 6 | 自定义查表算子实现量化部署
算法·自动驾驶
冬夜戏雪4 小时前
java学习 leetcode 二分查找 图论
java·学习·leetcode
火车叨位去19495 小时前
力扣top100(day02-05)--二叉树 02
算法·leetcode·职场和发展
James. 常德 student5 小时前
leetcode-hot-100 (图论)
算法·leetcode·图论
郝学胜-神的一滴5 小时前
C++中的`auto`与`std::any`:功能、区别与选择建议
开发语言·c++·程序人生·算法