问题:
初解:
虽然通过了但是有点拉跨:
主要思路就是用一个一维数组来存为0的位置:
- i作为索引
- j+1作为值,完成二维数组的功能
具体行和列清零目前还没有想到好的方法:
- 行之间用0 vector代替
- 但是列向量不知道怎么效率更高,还是非常笨的用循环赋值为0。这个过程中也有重复赋值的问题。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int row = matrix.size();
int cow = matrix[0].size();
int* zero2 = new int[row*cow]();//(1)不行
for (int i=0; i<row; ++i){
for (int j=0; j<cow; ++j){
if (matrix[i][j] == 0){
zero2[i*cow+j] = j+1;
}
}
}
for (int k=0; k<row*cow; ++k){
if (zero2[k] != 0){
matrix[k/cow] = vector<int>(cow,0);
for (int l=0; l<row; ++l){
matrix[l][zero2[k]-1] = 0;
}
}
}
}
};
使用两个标记变量
思路:因为消除的是行和列,我们按照从左到右的遍历思路,行首和列首可以作为flag以达到原地算法的目的。即:
- 从左到右遍历元素,遇到0时,把行首和列首设为0
- 从左到右遍历元素,遇行首或列首为0时,置0
- 以上需要特别注意的是第一行或者第一列有0的情况,此时需要用单独的标记变量先标记,最后再统一把首行或首列置0
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int row = matrix.size();
int cow = matrix[0].size();
bool row0 = false;
bool cow0 = false;
for (int j=0; j<cow; ++j){
if(!matrix[0][j]){
row0 = true;
}
}
for (int i=0; i<row; ++i){
if(!matrix[i][0]){
cow0 = true;
}
}
for (int i=1; i<row; ++i){
for (int j=1; j<cow; ++j){
if (!matrix[i][j]){
matrix[i][0]=matrix[0][j]=0;
}
}
}
for (int i=1; i<row; ++i){
for (int j=1; j<cow; ++j){
if (!matrix[i][0] || !matrix[0][j]){
matrix[i][j]=0;
}
}
}
if (row0){
for(int j=0; j<cow; ++j){
matrix[0][j]=0;
}
}
if (cow0){
for(int i=0; i<row; ++i){
matrix[i][0]=0;
}
}
}
};
使用一个标记变量
思路与两个标记变量类似,只不过我们只使用第一列的flag变量
第一行的其他列仍然参与正常的使用各行第一列的原地标记
运算的时间复杂度O(mn)与空间复杂度(1)与使用两个标记相同,见仁见智吧。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
int flag_col0 = false;
for (int i = 0; i < m; i++) {
if (!matrix[i][0]) {
flag_col0 = true;
}
for (int j = 1; j < n; j++) {
if (!matrix[i][j]) {
matrix[i][0] = matrix[0][j] = 0;
}
}
}
for (int i = m - 1; i >= 0; i--) {
for (int j = 1; j < n; j++) {
if (!matrix[i][0] || !matrix[0][j]) {
matrix[i][j] = 0;
}
}
if (flag_col0) {
matrix[i][0] = 0;
}
}
}
};