给定一个m*n的矩阵,如果有一个元素是0,就把该元素所在的行和列上的元素全置为0,要求使用原地算法。
拓展:
你的算法有使用额外的空间吗?
一种比较直接的算法是利用O(m,n)的空间,但是这不是一个好的解法
使用简单的改进可以在O(m+n)的空间解决这个问题,但是还不是最佳的解法
你能在常量级的空间复杂度内解决这个问题吗?
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int m = matrix.size();
int n = matrix[0].size();
map<int,bool> row,col;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(matrix[i][j] == 0)
row[i] = col[j] = true;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
if(row[i] || col[j])
matrix[i][j] = 0;
}
}
}; //找到0,把它所在行列里不为的都设为-1(这里假设了矩阵里只有正值,
//当然设置为一个不会出现的值就可以了)
//找完之后遍历一次矩阵,把-1的全设置为0
//不过这个算法是三个for循环的复杂度,有点大,但是也能通过
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int n = matrix.size();
int m = matrix[0].size();
for(int i=0;i<n;i++)
for(int j =0;j<m;j++){
if(matrix[i][j]==0){
for(int k =0;k<n;k++)
if(matrix[k][j]!=0)
matrix[k][j] = -1;
for(int k =0;k<m;k++)
if(matrix[i][k]!=0)
matrix[i][k] = -1;
}
}
for(int i=0;i<n;i++)
for(int j =0;j<m;j++)
if(matrix[i][j]==-1)
matrix[i][j] = 0;
}
}; class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int row = matrix.size();
int colum = matrix[0].size();
vector<vector<int> > vec;
vector<int> v;
if(row == 0||colum == 0)
return;
for(int i=0;i<row;i++)
for(int j=0;j<colum;j++)
{
if(matrix[i][j]==0)
{
v.push_back(i);
v.push_back(j);
vec.push_back(v);
v.clear();
}
}
int size = vec.size();
for(int i=0;i<size;i++)
{
for(int j=0;j<colum;j++)
{
matrix[vec[i][0]][j]=0;
}
for(int k=0;k<row;k++)
{
matrix[k][vec[i][1]]=0;
}
}
return;
}
}; import java.util.HashSet;
public class Solution {
public void setZeroes(int[][] matrix) {
// 创建两个集合,分别保存要重置为0的行与列
HashSet<Integer> row = new HashSet();
HashSet<Integer> col = new HashSet();
// 遍历matrix,如果找到某数为0,将所在行与列存储到集合中。
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == 0) {
row.add(i);
col.add(j);
}
}
}
//将集合中保存的行数与列数分别遍历出来,分别将整行与整列置0
for (Object num : row.toArray())
for (int i = 0; i < matrix[0].length; i++) {
matrix[(int) num][i] = 0;
}
for (Object num : col.toArray())
for (int i = 0; i < matrix.length; i++) {
matrix[i][(int) num] = 0;
}
}
}
void setZeroes(vector<vector<int> > &matrix) {
vector<pair<int,int>> vec;
int m = matrix.size();
int n = matrix[0].size();
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
if(matrix[i][j] == 0)
vec.push_back(make_pair(i, j));
for(int i = 0; i < vec.size(); ++i){
int x = vec[i].first;
int y = vec[i].second;
for(int j = 0; j < n;++j)
matrix[x][j] = 0;
for(int j = 0; j < m;++j)
matrix[j][y] = 0;
}
} 通过两个一维数组记录要进行标记的行和列
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
vector<int>hang;
vector<int>lie;
int m = matrix.size();
int n = matrix[0].size();
for(int i = 0;i<m;i++)
for(int j = 0;j<n;j++)
if(matrix[i][j]==0)
{
hang.push_back(i);
lie.push_back(j);
}
int l1 = hang.size();
int l2 = lie.size();
for(int i =0;i<l1;i++)
for(int j = 0;j<n;j++)
matrix[hang[i]][j]=0;
for(int i =0;i<l2;i++)
for(int j = 0;j<m;j++)
matrix[j][lie[i]]=0;
}
}; class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
vector<pair<int,int>>m;
for(int i=0;i<matrix.size();i++)
{
for(int j=0;j<matrix[0].size();j++)
{
if(matrix[i][j]==0)
{
pair<int,int>p={i,j};
m.push_back(p);
}
}
}
for(int k=0;k<m.size();k++)
{
int x=m[k].first,y=m[k].second;
for(int i=0;i<matrix.size();++i)
matrix[i][y]=0;
for(int j=0;j<matrix[0].size();++j)
matrix[x][j]=0;
}
}
};
class Solution {
//使用第一行和第一列来记录行和列的置0情况
//想要记录它们自己是否要置0,只需要两个变量(一个是第一行,一个是第一列)就可以了。
//然后就是第一行和第一列,如果要置0,就把它的值赋成0(反正它最终也该是0,无论第一行或者第一列有没有0),否则保留原值。
//然后根据第一行和第一列的记录对其他元素进行置0。
//最后再根据前面的两个标记来确定是不是要把第一行和第一列置0就可以了。
//这样的做法只需要两个额外变量,所以空间复杂度是O(1)。
//时间上需要进行两次扫描,一次确定行列置0情况,一次对矩阵进行实际的置0操作,所以总的时间复杂度是O(m*n)
public:
void setZeroes(vector<vector<int> > &matrix) {
int rows = matrix.size();
if(rows == 0) return;
int cols = matrix[0].size();
bool r0 = 0;
for(int i = 0; i < rows; i++)
if(matrix[i][0] == 0)
{
r0 = 1;
break;
}
bool c0 = 0;
for(int i = 0; i < cols; i++)
if(matrix[0][i] == 0)
{
c0 = 1;
break;
}
for(int i = 1; i < rows; i++)
{
for(int j = 1; j < cols; j++)
{
if(matrix[i][j] == 0)
{
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for(int i = 1; i < rows; i++)
{
for(int j = 1; j < cols; j++)
if(matrix[i][0] == 0 || matrix[0][j] == 0)
matrix[i][j] = 0;
}
if(r0 == 1)
for(int i = 0; i < rows; i++)
matrix[i][0] = 0;
if(c0 == 1)
for(int i = 0; i < cols; i++)
matrix[0][i] = 0;
}
}; class Solution {
};
//时间复杂度O(mn),空间复杂度O(1)
//利用第一行和第一列的空间做记录
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
const int row = matrix.size();
const int col = matrix[0].size();
bool row_flg = false, col_flg = false;
//判断第一行和第一列是否有零,防止被覆盖
for (int i = 0; i < row; i++)
if (0 == matrix[i][0]) {
col_flg = true;
break;
}
for (int i = 0; i < col; i++)
if (0 == matrix[0][i]) {
row_flg = true;
break;
}
//遍历矩阵,用第一行和第一列记录0的位置
for (int i = 1; i < row; i++)
for (int j = 1; j < col; j++)
if (0 == matrix[i][j]) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
//根据记录清零
for (int i = 1; i < row; i++)
for (int j = 1; j < col; j++)
if (0 == matrix[i][0] || 0 == matrix[0][j])
matrix[i][j] = 0;
//最后处理第一行
if (row_flg)
for (int i = 0; i < col; i++)
matrix[0][i] = 0;
if (col_flg)
for (int i = 0; i < row; i++)
matrix[i][0] = 0;
}
};
public class Solution {
public void setZeroes(int[][] matrix) {
boolean row = false,col=false;
for (int i = 0; i < matrix[0].length; i ++ ) if(matrix[0][i] == 0) row = true;
for (int i = 0; i < matrix.length; i ++ ) if(matrix[i][0] == 0) col = true;
for (int i = 1; i < matrix.length; i ++ ) {
for (int j = 1; j < matrix[0].length; j ++ ) {
if(matrix[i][j] == 0) {
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (int i = 1; i < matrix.length; i ++ ) {
for (int j = 1; j < matrix[0].length; j ++ ) {
if(matrix[0][j]==0||matrix[i][0]==0) matrix[i][j] = 0;
}
}
if(row) for (int i = 0; i < matrix[0].length; i ++ ) matrix[0][i] = 0;
if(col) for (int i = 0; i < matrix.length; i ++ ) matrix[i][0] = 0;
}
}
class Solution {
public:
void setZeroes(vector<vector<int> >& matrix) {
vector<int>vi, vj;//定义两个数组分别存0位置的行标和列标
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[0].size(); j++) {
if (matrix[i][j] == 0){
vi.push_back(i);
vj.push_back(j);
}
}
}
for (int k = 0; k < vi.size(); k++)
{
for (int i = 0; i < matrix.size(); i++) {//matrix.size()为矩阵的行数
matrix[i][vj[k]]=0;//把0所在位置的那一列都赋值为0
}
for (int j = 0; j < matrix[0].size(); j++){//matrix[0].size()矩阵列数
matrix[vi[k]][j]=0;//把0所在位置的那一行都赋值为0
}
}
// cout<<matrix.size()<<"行"<<matrix[0].size()<<
// "列"<<endl<<"有"<<vi.size()<<"个0元素"<<
// "位置是"<<vi[0]<<","<<vj[0];
}
}; package com.zrar.arask.data.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @program: tax2020
* @description: 编程题
* @author: fubowen
* @create: 2021-02-22 09:16
**/
public class Solution {
static class point{
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public static void setZeroes(int[][] matrix) {
//遍历矩阵 找到0的点 设置值为零
//存0的点 坐标
List<point> list=new ArrayList<>();
for(int i=0;i<matrix.length;i++){
int[] row=matrix[i];
for(int j=0;j<row.length;j++){
if(row[j]==0){
point point = new point();
point.setX(i);
point.setY(j);
list.add(point);
}
}
}
int xlength=matrix[0].length;
int ylength=matrix.length;
for (point point : list) {
for(int i=0;i<ylength;i++){
matrix[i][point.getY()]=0;
}
for(int i=0;i<xlength;i++){
matrix[point.getX()][i]=0;
}
}
}
}
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int m = matrix.size();
int n = matrix[0].size();
int i, j;
set<int> set_m, set_n;
for(i = 0;i < m;i++)
for(j = 0;j < n;j++)
{
if(0 == matrix[i][j])
{
set_m.insert(i);
set_n.insert(j);
}
}
for(auto j = set_m.begin();j != set_m.end();j++)
{
for(int k = 0;k < n;k++)
matrix[*j][k] = 0;
}
for(auto j = set_n.begin();j != set_n.end();j++)
{
for(int k = 0;k < m;k++)
matrix[k][*j] = 0;
}
}
}; public class Solution {
public void setZeroes(int[][] matrix) {
int n=matrix.length; //行
int m=matrix[0].length; //列
//先遍历行n,再遍历列m
int[][] mat=new int[n][m]; //新建一个二维数组,用来做行列置零操作
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
mat[i][j]=matrix[i][j];
}
利用第一行和第一列存储状态:
//
// Created by jt on 2020/9/25.
//
#include <vector>
using namespace std;
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
bool firstRowHas0 = false, firstColHas0 = false;
for (int i = 0; i < matrix.size(); ++i) {
if (matrix[i][0] == 0) { firstColHas0 = true; break; }
}
for (int i = 0; i < matrix[0].size(); ++i) {
if (matrix[0][i] == 0) { firstRowHas0 = true; break; }
}
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[0].size(); ++j) {
if (matrix[i][j] == 0) {
matrix[0][j] = 0; matrix[i][0] = 0;
}
}
}
for (int i = 1; i < matrix.size(); ++i) {
for (int j = 1; j < matrix[0].size(); ++j){
if (matrix[0][j] == 0 || matrix[i][0] == 0) matrix[i][j] = 0;
}
}
if (firstRowHas0) {
for (int i = 0; i < matrix[0].size(); ++i) {
matrix[0][i] = 0;
}
}
if (firstColHas0) {
for (int i = 0; i < matrix.size(); ++i) {
matrix[i][0] = 0;
}
}
}
};
public void setZeroes(int[][] matrix) {
if(matrix == null){
return;
}
int rowLength = matrix.length;
int colLength = matrix[0].length;
boolean firstRow = false;
boolean firstCol = false;
//判断第一行是否存在0
for(int i = 0; i < colLength; i++){
if(matrix[0][i] == 0){
firstRow = true;
break;
}
}
//判断第一列是否存在0
for(int i = 0; i < rowLength; i++){
if(matrix[i][0] == 0){
firstCol = true;
break;
}
}
//遍历二行二列开始的二维数组
for(int i = 1;i < rowLength; i++){
for(int j = 1; j < colLength; j++){
if(matrix[i][j] == 0){
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
//根据第一行置零, 需从1开始,否则如果matrix[0][0] = 0 会影响接下来第一列置零
for(int i = 1;i < colLength; i++){
if(matrix[0][i] == 0){
for(int j = 1; j < rowLength;j++){
matrix[j][i] = 0;
}
}
}
//根据第一列置零,需从1开始,否则会被根据第一行置零结果影响,如果matrix[0][0] = 0
for(int i = 1;i < rowLength; i++){
if(matrix[i][0] == 0){
for(int j = 1;j < colLength; j++){
matrix[i][j] = 0;
}
}
}
//根据标志将一行一列置0
if(firstRow){
for(int i = 0;i < colLength; i++){
matrix[0][i] = 0;
}
}
if(firstCol){
for(int i = 0;i < rowLength; i++){
matrix[i][0] = 0;
}
}
} 思路:
利用第一行、第一列来标记,注意第一行、第一列被覆盖问题
1、先不处理第一行、第一列,只标记其一开始是否有0(row_flag, col_flag);
2、然后从第二行第二列开始处理,若该位置为0,则将第一行、第一列对应位置置为0;
3、从第二行第二列开始,若其行列数对应第一行、第一列的值为0,则置0
4、若row_flag, col_flag为真,置0第一行,第一列
public class Solution {
public void setZeroes(int[][] matrix) {
int row = matrix.length;
int col =matrix[0].length;
boolean row_flag=false,col_flag=false;
//利用第一行、第一列来标记
//注意第一行、第一列被覆盖问题,先不处理第一行、第一列,只标记其一开始是否有0
//第一行
for(int j=0; j<col;j++)
{
if(matrix[0][j]==0)
{
row_flag=true;
break;
}
}
//第一列
for(int i=0; i<row;i++)
{
if(matrix[i][0]==0)
{
col_flag=true;
break;
}
}
//第一行第一列置0
for(int i=1;i<row;i++)
{
for(int j=1;j<col;j++)
{
if(matrix[i][j]==0)
{
matrix[i][0]=0;
matrix[0][j]=0;
}
}
}
//对应行、列置0
for(int i=1;i<row;i++)
{
for(int j=1;j<col;j++)
{
if(matrix[i][0]==0 || matrix[0][j]==0)
{
matrix[i][j]=0;
}
}
}
if(row_flag==true)
{
for(int i=0;i<col;i++)
{
matrix[0][i]=0;
}
}
if(col_flag==true)
{
for(int i=0;i<row;i++)
{
matrix[i][0]=0;
}
}
}
} class Solution {
public:
unordered_set<int> ST1,ST2;//ST1记住已经被发现的0的行坐标,ST2记住已经被发现的0的行坐标
void setZeroes(vector<vector<int> > &matrix) {
for(int i=0;i<matrix.size();i++) {
for(int j=0;j<matrix[0].size();j++) {
if(matrix[i][j]==0) {
if(ST1.find(i)==ST1.end()) ST1.insert(i);
if(ST2.find(j)==ST2.end()) ST2.insert(j);
}
}
}
for(unordered_set<int>::iterator i=ST1.begin();i!=ST1.end();i++) {
for(int j=0;j<matrix[0].size();j++) {
matrix[*i][j]=0;
}
}
for(unordered_set<int>::iterator j=ST2.begin();j!=ST2.end();j++) {
for(int i=0;i<matrix.size();i++) {
matrix[i][*j]=0;
}
}
}
};