ctci/1. Arrays and strings/1.8. zero_matrix.md

74 lines
2.6 KiB
Markdown

# 1.8. Zero matrix
## Given an M x N matrix, if an element is 0, make the entire row and column 0
> Example:
```python
imat = [[1,2,0,9],
[4,0,6,8],
[7,8,9,1]]
omat = [[0,0,0,0],
[0,0,0,0],
[7,0,0,1]]
```
## First idea
Intuitivelly I'd find all initial 0 elements, and then 0-ize the respective rows and cols. Only initial 0s must be 0-ized, not new ones. If I have to save all initial zeroes, that's already O(NM). Then iterate through all 0s again, and 0-ize. Which in turn takes O(k(N+M)). If there's a 0 in all rows/cols, the whole matrix is 0 and we can break the loop.
## Hints
1. Find all zeroes first, got it
2. Use O(M+N) space instead of O(NM)? What info do you really need from the list of zeroes?
> example:
```python
list_zeroes = [(0,2), (1,1)]
```
The only info we need is which rows and cols are 'touched', in this case rows:0,1, cols:1,2. Then just go to those rows and delete all cols, and go to all cols and delete all rows.
```python
rows = []
cols = []
for i in range(M):
for j in range(N):
if len(rows) == M or len(cols) == N:
return 0 # zero matrix
if imat[i][j] == 0:
if i not in rows:
rows.append(i)
if j not in cols:
cols.append(j)
for r in rows:
for j in range(N):
imat[r][j] = 0
for c in cols:
for i in range(N):
imat[i][c] = 0
return imat
```
If all rows or all cols are represented, the whole matrix becomes 0.
## Third hint
Reduce additional storage of 0s by using the matrix itself for data storage? In my implementation, space complexity it at most O(M+N) but no idea how to 'flag' these 0es in the matrix itself...
## Solution
Use two arrays to keep track of all the rows with zeros and all the columns with zeros, and then nullify rows and columns based on the values in these arrays. The two arrays are boolean arrays of length N and length M.
Use a bit vector instead of boolean arrays. We can reduce the space to O(1) by using the first column as a replacement for the `row` array and the first row as a replacement for the `column` array.
1. Check if the first row and first column have any zeroes, and set variables `rowHasZero` and `columnHasZero`
2. Iterate through the rest of the matrix, setting imat[i][0] and imat[0][j] to zero whenever there's a zero in imat[i][j].
3. Iterate through the rest of matrix, nullifying row `i` if there's a zero in `imat[i][0]`
4. Iterate through the rest of matrix, nullifying col `j` if there's a zero in `imat[0][j]`
5. Nullify the first row and first column if necessary, based on values from step1.