Problem
Given an m x n matrix of 0s and 1s, provide an algorithm such that if an element is 0, its entire row and column is set to 0
OR
Given an m x n
integer matrix matrix
, if an element is 0
, set its entire row and column to 0
’s.
You must do it in place.
Follow Up:
Can you do it in one pass?
Examples
Example 1:
$$ \begin{bmatrix} 1 & 0 & 1 & 1 & 0 \\ 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 0 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix} \Longrightarrow \begin{bmatrix} 0 & \colorbox{orange} 0 & 0 & 0 & \colorbox{orange} 0 \\ \colorbox{orange} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 \\ 0 & \colorbox{orange} 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 1 & 0 \end{bmatrix} $$
|
|
Example 2:
$$ \begin{bmatrix} 0 & 1 & 2 & 0 \\ 3 & 4 & 5 & 2 \\ 1 & 3 & 1 & 5 \end{bmatrix} \Longrightarrow \begin{bmatrix} \colorbox{orange} 0 & 0 & 0 & \colorbox{orange} 0 \\ 0 & 4 & 5 & 0 \\ 0 & 3 & 1 & 0 \end{bmatrix} $$
|
|
Solution
Method 1 - Using the set as Extra Space
In this approach we can do :
- Scan the matrix, store the numbers of rows and columns that will be set to zero to two sets
- Iterate through those two sets and set corresponding row and col to zeros.
Code
|
|
Complexity
- ⏰ Time complexity:
O(m*n)
- 🧺 Space complexity:
O(m+n)
Method 2 - Using boolean array as extra space
Also, as SET takes more space, rather than using SET, we can use a simple boolean arrays.
Code
|
|
Complexity
- ⏰ Time complexity:
O(m*n)
- 🧺 Space complexity:
O(m+n)
Method 3 - Using first row and column as boolean array
This method is a space optimized version of above method 1. This method uses the first row and first column of the input matrix in place of the auxiliary arrays rowBooleanArray[]
and colBooleanArray[]
of method 1.
So what we do is: first take care of first row and column and store the info about these two in two flag variables rowFlag and colFlag. Once we have this info, we can use first row and first column as auxiliary.
We now need 2 passes.
- I use first column and first row as markers to know where are rows/cols with only 1’s. Then, there are 2 variables
r
andc
to remember if first row/column are all 1’s also. So the first pass sets the markers and resets the rest to 0’s. - The second pass sets 1 in places where rows and cols where marked to be 1, and resets 1st line/col depending on
r
andc
.
Now apply method 1 for submatrix (matrix excluding first row and first column) of size (M-1)*(N-1)
:
- Scan the first row and set a variable rowFlag to indicate whether we need to set all 0s in first row or not.
- Scan the first column and set a variable colFlag to indicate whether we need to set all 0s in first column or not.
- Use first row and first column as the auxiliary arrays row[] and col[] respectively, consider the matrix as submatrix starting from second row and second column and apply method 1.
- Finally, using rowFlag and colFlag, update first row and first column if needed.
Psuedocode
|
|
Code
|
|
Complexity
- ⏰ Time complexity:
O(m*n)
- 🧺 Space complexity:
O(1)
Method 3 - Doing it in One Pass
So the idea is to use the values in the last row/column as a flag to indicate whether all of the values in the corresponding column/row are 1s. Using a Zig Zag scan through the entire matrix EXCEPT the final row/column. At each element, you set the value in the final row/column as to the logical AND of itself with the value in the current element. In other words, if you hit a 0, the final row/column will be set to 0. If you hit a 1, the value in the final row/column will be 1 only if it was 1 already. In any case set the current element to 0.
When you’ve finished, your final row/column should have 1s iff the corresponding column/row was filled with 1s.
Do a linear scan through the final row and column and looking for 1s. Set 1s in the corresponding elements in body of the matrix where the final row and column are both 1s.
Coding it will be tricky to avoid off-by-one errors etc but it should work in one pass.