小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
leetcode73-矩阵置零
前文
本文为菜鸟的刷题记录,仅用作笔记使用,并非最佳解决方案。
题目信息
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
进阶:
一个直观的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。 你能想出一个仅使用常量空间的解决方案吗?
解题思路分析
解法1
很容易想到使用标记数组进行记录,先进行一次遍历,记录所有的位置是否为0.再进行二次遍历,如果数值是0,则对对应的行列进行置零操作。代码如下:
public void setZeroes(int[][] matrix) {
int[] rows = new int[matrix.length];
int[] columns;
if(matrix.length > 0){
columns = new int[matrix[0].length];
}else{
columns = new int[0];
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if(matrix[i][j] == 0){
rows[i] = 1;
columns[j] = 1;
}
}
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if(rows[i] == 1 || columns[j] == 1){
matrix[i][j] = 0;
}
}
}
}
解法2
解法2主要是对于空间复杂度的降低。利用数组的第一行第一列作为标记列。首先采用数组的第一行、第一列作为记录。遍历后续的数据,如果为0则将第一行、第一列进行对应标记。二次遍历时再将对应的行列进行处理。要注意首先要记录一下原始记录第一行、第一列是否有0,如果有需要把第一行、第一列置为0.代码如下:
public void setZeroes(int[][] matrix) {
// 记录最开始是否为0
boolean row = false;
boolean column = false;
for (int i = 0; i < matrix.length; i++) {
if(matrix[i][0] == 0){
column = true;
}
}
if(matrix.length > 0){
for (int i = 0; i < matrix[0].length; i++) {
if(matrix[0][i] == 0){
row = true;
}
}
}
// 标记遍历
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if(matrix[i][j] == 0){
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// 处理
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if(matrix[i][0] == 0 || matrix[0][j] == 0){
matrix[i][j] = 0;
}
}
}
// 处理如果最开始就是0的情况
if(row){
for (int i = 0; i < matrix[0].length; i++) {
matrix[0][i] = 0;
}
}
if(column){
for (int i = 0; i < matrix.length; i++) {
matrix[i][0] = 0;
}
}
}
复杂度分析
- 时间复杂度 o(m*n)
- 空间复杂度 o(m*n) o(1)
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。