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

2.6 KiB

1.8. Zero matrix

Given an M x N matrix, if an element is 0, make the entire row and column 0

Example:

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:

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.

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.