矩阵置零
给定一个 mxn 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。**
示例 1:

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
解法及思路
用第一行和第一列做标记
核心思想:
不用额外数组,直接用矩阵的第一行和第一列来标记 matrix[i][0] = 0 → 第i行要置零 matrix[0][j] = 0 → 第j列要置零
但是问题来了:
第一行和第一列本身也可能要置零 如果用它们做标记,就分不清: matrix[0][j]=0 是"原本就是0"还是"标记"?
所以需要额外两个变量:
java
boolean firstRowZero = false; // 第一行本身是否要置零
boolean firstColZero = false; // 第一列本身是否要置零
举例:
matrix = [
1, 2, 3, 4,
5, 0, 7, 8,
9, 10, 0, 12,
13, 14, 15, 16
]
第1步:检查第一行是否有0
第一行:[1, 2, 3, 4]
没有0 → firstRowZero = false
第2步:检查第一列是否有0
第一列:[1, 5, 9, 13]
没有0 → firstColZero = false
第3步:用第一行/列标记内层
遍历内层:
i=1, j=1: matrix[1][1]=0 matrix[1][0] = 0 ← 标记第1行 matrix[0][1] = 0 ← 标记第1列 i=1, j=2: matrix[1][2]=7,不是0 i=1, j=3: matrix[1][3]=8,不是0 i=2, j=1: matrix[2][1]=10,不是0 i=2, j=2: matrix[2][2]=0 matrix[2][0] = 0 ← 标记第2行 matrix[0][2] = 0 ← 标记第2列 i=2, j=3: matrix[2][3]=12,不是0 i=3, j=1: matrix[3][1]=14,不是0 i=3, j=2: matrix[3][2]=15,不是0 i=3, j=3: matrix[3][3]=16,不是0
标记后矩阵:
[1, 0, 0, 4] ← matrix[0][1]=0, matrix[0][2]=0 [0, 0, 7, 8] ← matrix[1][0]=0 [0, 10, 0, 12] ← matrix[2][0]=0 [13, 14, 15, 16]
第一行:标记了第1列和第2列
第一列:标记了第1行和第2行
第4步:根据标记置零内层
遍历内层:
i=1, j=1: matrix[1][0]=0 → 置0 矩阵:[1,0,0,4] [0,0,7,8] [0,10,0,12] [13,14,15,16] i=1, j=2: matrix[0][2]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,8] [0,10,0,12] [13,14,15,16] i=1, j=3: matrix[1][0]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,10,0,12] [13,14,15,16] i=2, j=1: matrix[2][0]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,12] [13,14,15,16] i=2, j=2: matrix[2][0]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,12] [13,14,15,16] i=2, j=3: matrix[0][2]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,0] [13,14,15,16] i=3, j=1: matrix[3][0]=13, matrix[0][1]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,0] [13,0,15,16] i=3, j=2: matrix[0][2]=0 → 置0 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,0] [13,0,0,16] i=3, j=3: matrix[3][0]=13, matrix[0][3]=4 → 不置零 矩阵:[1,0,0,4] [0,0,0,0] [0,0,0,0] [13,0,0,16]
置零后矩阵:
[1, 0, 0, 4] [0, 0, 0, 0] [0, 0, 0, 0] [13, 0, 0, 16]
第5步:处理第一行
firstRowZero = false → 不处理
[1, 0, 0, 4] [0, 0, 0, 0] [0, 0, 0, 0] [13, 0, 0, 16]
第6步:处理第一列
firstColZero = false → 不处理
[1, 0, 0, 4] [0, 0, 0, 0] [0, 0, 0, 0] [13, 0, 0, 16]
最终结果
[1, 0, 0, 4] [0, 0, 0, 0] [0, 0, 0, 0] [13, 0, 0, 16] ✅
java
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
boolean firstRowZero = false;
boolean firstColZero = false;
// 第1步:检查第一行
for (int j = 0; j < n; j++) {
if (matrix[0][j] == 0) firstRowZero = true;
}
// 第2步:检查第一列
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) firstColZero = true;
}
// 第3步:标记
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0; // 标记行
matrix[0][j] = 0; // 标记列
}
}
}
// 第4步:置零
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 第5步:处理第一行
if (firstRowZero) {
for (int j = 0; j < n; j++) matrix[0][j] = 0;
}
// 第6步:处理第一列
if (firstColZero) {
for (int i = 0; i < m; i++) matrix[i][0] = 0;
}
}
}
螺旋矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
解法及思路
边界收缩
用四个边界
top = 0 (上边界) bottom = m - 1 (下边界) left = 0 (左边界) right = n - 1 (右边界)
按顺序遍历:
1. 从左到右:top 行,left → right 2. 从上到下:right 列,top → bottom 3. 从右到左:bottom 行,right → left 4. 从下到上:left 列,bottom → top 每遍历完一条边,收缩对应边界
输入:
[1, 2, 3] [4, 5, 6] [7, 8, 9]
初始边界:
top=0, bottom=2, left=0, right=2
第1步:从左到右(top行)
top=0, left→right: 1, 2, 3 结果:[1, 2, 3] top++ → top=1
第2步:从上到下(right列)
right=2, top→bottom: 6, 9 结果:[1, 2, 3, 6, 9] right-- → right=1
第3步:从右到左(bottom行)
bottom=2, right→left: 8, 7 结果:[1, 2, 3, 6, 9, 8, 7] bottom-- → bottom=1
第4步:从下到上(left列)
left=0, bottom→top: 4 结果:[1, 2, 3, 6, 9, 8, 7, 4] left++ → left=1
第5步:从左到右(top行)
top=1, left→right: 5 结果:[1, 2, 3, 6, 9, 8, 7, 4, 5] top++ → top=2
结束:top=2 > bottom=1,退出循环
结果:[1, 2, 3, 6, 9, 8, 7, 4, 5] ✅
java
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
if (matrix == null || matrix.length == 0) return result;
int top = 0, bottom = matrix.length - 1;
int left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
// 1. 从左到右
for (int j = left; j <= right; j++) {
result.add(matrix[top][j]);
}
top++;
// 2. 从上到下
for (int i = top; i <= bottom; i++) {
result.add(matrix[i][right]);
}
right--;
// 3. 从右到左(需要判断是否还有行)
if (top <= bottom) {
for (int j = right; j >= left; j--) {
result.add(matrix[bottom][j]);
}
bottom--;
}
// 4. 从下到上(需要判断是否还有列)
if (left <= right) {
for (int i = bottom; i >= top; i--) {
result.add(matrix[i][left]);
}
left++;
}
}
return result;
}
}
旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在****原地**** 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
解法及思路
先转置,再反转
顺时针旋转 90 度 = 转置 + 每行反转
第1步:转置(行列互换) [1, 2, 3] [1, 4, 7] [4, 5, 6] → [2, 5, 8] [7, 8, 9] [3, 6, 9] 第2步:每行反转 [1, 4, 7] [7, 4, 1] [2, 5, 8] → [8, 5, 2] [3, 6, 9] [9, 6, 3] ✅
输入:
[1, 2, 3] [4, 5, 6] [7, 8, 9]
第1步:转置
转置就是 matrix[i][j] 和 matrix[j][i] 交换。
i=0, j=1: 交换 matrix[0][1] 和 matrix[1][0] 2 和 4 交换 [1, 4, 3] [2, 5, 6] [7, 8, 9] i=0, j=2: 交换 matrix[0][2] 和 matrix[2][0] 3 和 7 交换 [1, 4, 7] [2, 5, 6] [3, 8, 9] i=1, j=2: 交换 matrix[1][2] 和 matrix[2][1] 6 和 8 交换 [1, 4, 7] [2, 5, 8] [3, 6, 9] 转置完成!
第2步:每行反转
第0行:[1, 4, 7] → [7, 4, 1] 第1行:[2, 5, 8] → [8, 5, 2] 第2行:[3, 6, 9] → [9, 6, 3] 结果: [7, 4, 1] [8, 5, 2] [9, 6, 3] ✅
java
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
// 第1步:转置
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {// 注意:j 从 i+1 开始,只遍历上三角,避免重复交换
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 第2步:每行反转
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;
}
}
}
}
搜索二维矩阵||
编写一个高效的算法来搜索 m xn 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。
示例 1:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true
示例 2:

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false
解法及思路
从右上角开始
关键:右上角的元素有特殊性质。
右上角:15 比15小的:左边所有元素(同一行左边) 比15大的:下边所有元素(同一列下边) 所以: target < 15 → 往左走(排除这一列) target > 15 → 往下走(排除这一行) target == 15 → 找到
为什么从右上角?
因为右上角是"这一行最大,这一列最小" 可以明确判断往哪走
输入:
[1, 4, 7, 11, 15] [2, 5, 8, 12, 19] [3, 6, 9, 16, 22] [10, 13, 14, 17, 24] [18, 21, 23, 26, 30] target = 5
从右上角开始:
初始:row=0, col=4 matrix[0][4] = 15 15 > 5 → 往左走,col=3 matrix[0][3] = 11 11 > 5 → 往左走,col=2 matrix[0][2] = 7 7 > 5 → 往左走,col=1 matrix[0][1] = 4 4 < 5 → 往下走,row=1 matrix[1][1] = 5 5 == 5 → 找到!✅
java
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m=matrix.length;
int n=matrix[0].length;
int row = 0; // 从右上角开始
int col = n - 1;
while(row<m&&col>=0){
if(matrix[row][col]==target){
return true;
}else if(matrix[row][col]>target){
col--;//大了,往左
}else{
row++;//小了,往下
}
}
return false;
}
}