Reputation: 121
Given a matrix, if a cell contains 0, then we have make entire row and column corresponding to the cell as 0. For example, if
1 2 3
M = 0 4 5
4 2 0
then the output should be
0 2 0
0 0 0
0 0 0
The method I thought is as follows
row[]
and col[]
. If a cell(i,j) contains 0 then, mark row[i]
and col[j]
as 0.(Initially row[]
and col[]
contains all 1s).row[i]
or col[j]
is 0, then put cell(i,j) as 0.This takes O(m*n) time and O(m+n) space.
How to optimize it further specially in terms of space.Any suggestions for improving time complexity are also welcomed.
Upvotes: 5
Views: 5595
Reputation: 1
Simple and easy answer: <2 nested loop> to search through all columns and rows you find any cell = 0 through all column and set it to zeros through all row and set it to zeros. let me know if it not clear to record video for it.
Int main()
{
//example matrix dimension rows(r=6) * columns (c=3)
int r = 6;
int c = 3;
int matrix[r][c];
for(int i=0; i<r; ++i){
for(int j=0 ; j < c ; ++j){
if(matrix[i][j] == 0){
for(int ii=0; ii<r; ++ii){
Matrix[ii][j] = 0 ;
}
for(int jj=0; jj<c; ++jj){
Matrix[i][jj] = 0 ;
}
}
}
}
}
Upvotes: 0
Reputation: 6246
Here is an algorithm can do it in O(M*N) time and O(1) space : -
- Find the max element in the matrix .
- Mat[i][j] = max - Mat[i][j] for all (i,j)
- Notice that Mat[i][j] will only have positive values.
- Use negetive values as sentinels and Mat[i][j] = max as zeros.
- Retrieve original values as Mat[i][j] = max - Mat[i][j]
Upvotes: 0
Reputation: 150
Aha, this is an old question.
Use one boolean variate(isZeroInFirstRow
) saving if first row has zero element(s) or not and one boolean variate(isZeroInFirstCol
) saving if first column has zero element(s) or not.
Then, traverse the whole matrix. If cell(i,j)==0
, then set cell(0,j) and cell(i,0) to 0.
Traverse the first row of the matrix. If cell(0,j)==0
, then set all elements in column(j) to 0.
Traverse the first column of the matrix. If cell(i,0)==0
, then set all elements in row(i) to 0.
If isZeroInFirstRow==true
, set all elements in row(0) to 0.
If isZeroInFirstCol==true
, set all elements in column(0) to 0.
Upvotes: 10
Reputation: 340218
You can use your algorithm without allocating and auxiliary row or column by searching the matirx for a row that contains no zeros and a column that contains no zero elements.
If either of these searches fails, then the resulting matrix will all zeros, so your work is done by simply setting all elements to zero.
Otherwise, use the row and colum you found as the bookkeeping row and column you mentioned, setting the corresponding element to zero as you find zeros in the remainder of the matrix. Once that pass is done you walk the bookkeeping row, setting the matix columns to zeros for any zero found in the bookkeeping row, similarly for the aux column.
Upvotes: 0
Reputation: 8032
If you are concerned with storage you may think of using some sparse matrix storage formats to store the resulting matrix, and then free the original dense input.
An example of what I am proposing may be the following (implementing COO format) which should take O(M*N) time:
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstddef>
using namespace std;
int main()
{
constexpr size_t M = 3;
constexpr size_t N = 3;
int matrix[M][N] = {
{1, 2, 3},
{0, 4, 5},
{4, 2, 0}
};
vector<size_t> markedRows;
vector<size_t> markedColumns;
// Search for zeroes
for (size_t ii = 0; ii < M; ++ii) {
for(size_t jj = 0; jj < N; ++jj) {
if (matrix[ii][jj] == 0) {
markedRows.push_back (ii);
markedColumns.push_back(jj);
}
}
}
// Sort columns (rows are ordered by construction)
sort(markedColumns.begin(),markedColumns.end());
// Eliminate duplicates
markedRows.erase (unique(markedRows.begin() ,markedRows.end()) ,markedRows.end() );
markedColumns.erase(unique(markedColumns.begin(),markedColumns.end()),markedColumns.end());
// Construct COO matrix format
vector<size_t> irow;
vector<size_t> icol;
vector<int> val;
for (size_t ii = 0; ii < M; ++ii) {
for(size_t jj = 0; jj < N; ++jj) {
if ( ( find(markedRows.begin() ,markedRows.end() ,ii) == markedRows.end() ) &&
( find(markedColumns.begin(),markedColumns.end(),jj) == markedColumns.end() )
) {
irow.push_back(ii);
icol.push_back(jj);
val.push_back (matrix[ii][jj]);
}
}
}
// FROM HERE YOU NO LONGER NEED MATRIX, AND YOU CAN FREE THE STORAGE
// Print non zero entries
for( size_t ii = 0; ii < irow.size(); ++ii) {
cout << "A["<<irow[ii]<<","<<icol[ii]<<"] = "<<val[ii]<<endl;
}
return 0;
}
Upvotes: 1
Reputation: 95968
You can solve this in O(1) space. One solution is to iterate on the matrix, for each 0 you see, you fill the corresponding row/col with some character, 'X' for example.
When you finish, you should have something like that:
X 2 X
M= 0 X X
X X 0
Then you iterate again on the matrix and replace each 'X' with 0 to get:
0 2 0
M= 0 0 0
0 0 0
Upvotes: 1