题目描述:
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
示例 1:
输入: [ [1,1,1], [1,0,1], [1,1,1] ] 输出: [ [1,0,1], [0,0,0], [1,0,1] ]
示例 2:
输入: [ [0,1,2,0], [3,4,5,2], [1,3,1,5] ] 输出: [ [0,0,0,0], [0,4,5,0], [0,3,1,0] ]
进阶:
题干分析:
本题要求依旧比较简单,最粗暴的做法是将数组遍历,遇到0时将对应的行和列进行标记(这里不要用0标记,否则会判断失误);我们做进一步思考,发现并不需要反复对数组内所有元素进行标记,实际上我们只需要行和列的标记,至此解题思路就很明朗了;
思路分析:
我们需要新两个的数组来存放标记,标记最好选用BOOL类型,这样轻松写意,其实这里的做法就是进阶中的空间O(m+n);常数空间的做法应该如何完成?我的思路是借用数组空间的第一行和第一列,但这里会在标记后置零时给你带来新的问题,你需要先判断除去行列首尾的三个点,然后将行列首尾三个点单独拿出来判断,可以采用标记单独标记:
如果不将此三点单独拿出来讨论,会严重影响整个置零过程,可以结合图片思考一下;
下图为空间O(m+n)因未选取此类方法,固将示意图贴出来
到这里剩下的事情就是简单的递归循环了,其实了解思路后本题还是很简单的;
代码如下:(因为LETT_CODE中很多代码比我写的更加规范,固多有借鉴,侵删)
void setZeroes(int** matrix, int matrixRowSize, int matrixColSize) {
bool firstRowZero = false, firstColZero = false;//行列标记
int i, j;
for (i = 0; i < matrixRowSize; ++i) {
for (j = 0; j < matrixColSize; ++j) {
if (i != 0 && j != 0 && matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;//在行列上直接标记
} /*if*/else if (matrix[i][j] == 0) {
if (i == 0)
firstRowZero = true;
if (j == 0)
firstColZero = true;
}//else if
}//for-2
}//for-1
for (i = 1; i < matrixRowSize; ++i) {
for (j = 1; j < matrixColSize; ++j) {
if (matrix[i][0] == 0 || matrix[0][j] == 0)
matrix[i][j] = 0;
}//for-2
}//for-1
for (i = 0; firstColZero && i < matrixRowSize; ++i) {
matrix[i][0] = 0;
}//&&为短路判定,所以在这里不用担心多余的判定
for (j = 0; firstRowZero && j < matrixColSize; ++j) {
matrix[0][j] = 0;
} return ;//void函数建议各位也写一下return,个人习惯问题
}