题目:给定一个 m x n
的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
示例 1:
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]
示例 2:
输入: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]]
第一种解题思路+代码:
代码:
class Solution {
public void setZeroes(int[][] matrix) {
/*
思路:
1.判断矩阵是否为空,为空直接返回
1.遍历矩阵,找出矩阵中的0并记录
2.将记录所在位置0的行和列的所有元素都设为0
*/
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return; // 如果矩阵为空,直接返回
}
int rows = matrix.length;
int cols = matrix[0].length;
boolean[] zeroRows = new boolean[rows];
boolean[] zeroCols = new boolean[cols];
// 遍历矩阵,找到所有值为零的元素,记录对应的行和列
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == 0) {
zeroRows[i] = true;
zeroCols[j] = true;
}
}
}
// 将行置零
for (int i = 0; i < rows; i++) {
if (zeroRows[i]) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = 0;
}
}
}
// 将列置零
for (int j = 0; j < cols; j++) {
if (zeroCols[j]) {
for (int i = 0; i < rows; i++) {
matrix[i][j] = 0;
}
}
}
}
}
第二种解题思路+代码:
代码:
class Solution {
public void setZeroes(int[][] matrix) {
/*
思路:记录下0的值,将0值的行和列逐一填充为0,填充完后将原矩阵的值再记录进去,得到置零的新矩阵
*/
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return; // 如果矩阵为空,直接返回
}
int rows = matrix.length;
int cols = matrix[0].length;
// 用于记录零的位置
List<int[]> zeroPositions = new ArrayList<>();
// 遍历矩阵,记录所有零的位置
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == 0) {
zeroPositions.add(new int[]{i, j});
}
}
}
// 根据记录的零的位置,逐一将对应的行和列置零
for (int[] pos : zeroPositions) {
int row = pos[0];
int col = pos[1];
// 将当前行置零
for (int j = 0; j < cols; j++) {
matrix[row][j] = 0;
}
// 将当前列置零
for (int i = 0; i < rows; i++) {
matrix[i][col] = 0;
}
}
}
}
总结:这道题的解题思路差不多,都是记录矩阵中0的位置,再将0所对应位置下的行列置零,实现矩阵置零。同理可解其他数字的套路,依照该题的解法可以举一反三。第二种解法适合阵中零的个数较少的情况,如果矩阵中零的个数较少,这种方法效率较高;但如果零的个数较多,可能会导致效率降低。相比之下,使用第一行和第一列作为标记的方法在时间和空间复杂度上要更加高效,且避免了额外空间的使用,更适合大规模矩阵的处理。