73. Set Matrix Zeroes

73. Set Matrix Zeroes

Photo by Henry & Co. on Unsplash

Problem Statement

Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0's. (link)

You must do it in place.

Example 1:

Input: matrix = [[1,1,1],[1,0,1],[1,1,1]]
Output: [[1,0,1],[0,0,0],[1,0,1]]

Solution

Assume that for a given i and j, the value present at matrix[i][j] being 0 implies that we need to set all the elements in row i and column j to 0. Making 0 at a particular index should not affect its row and column.

Brute Force Approach - Using Extra space (mxn)

We create an additional matrix called visited with the same size. We iterate through the array, and if we find an element at (i, j) that is 0, we mark all the corresponding indices in visited as -1. Later, we reiterate over the original matrix and fill all the elements with 0 for which visited[i][j] is -1.

Time - O(mxn) x O(mxn)

Space - O(mxn)

class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;

        int[][] visited = new int[m][n];

        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(matrix[i][j]==0){
                    markRow(visited, i);
                    markCol(visited, j);
                }
            }
        }
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(visited[i][j]==-1){
                    matrix[i][j] = 0;
                }
            }
        }
    }

    public void markRow(int[][] visited, int row){
        for(int j=0; j<visited[0].length; j++){
            visited[row][j] = -1;
        }
    }

    public void markCol(int[][] visited, int col){
        for(int i=0; i<visited.length; i++){
            visited[i][col] = -1;
        }
    }
}

Optimal Approach - Using Extra Space (m+n)

Using Set - We go through each element present in the matrix and note down the row and column index in the row set and column set, respectively. We iterate through the matrix and check if the current row index or column index is present in our row or column sets, respectively. If it is present, we set the current element to 0.

Time - O(mxn) [For arrays/sets]

Space - O(m+n)

class Solution {
    public void setZeroes(int[][] matrix) {
        Set<Integer> rows = new HashSet<>();
        Set<Integer> cols = new HashSet<>();

        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                if(matrix[i][j]==0){
                    rows.add(i);
                    cols.add(j);
                }
            }
        }

        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                if(rows.contains(i) || cols.contains(j))
                    matrix[i][j] = 0;
            }
        }
    }
}

Using arrays - Same as the set approach, the only difference is that instead of using a set data structure, we use arrays. Here we make use of 2 arrays: row[] and col[]. If matrix[i][j] is 0, then we mark row[i] as 1 and col[j] as 1. During the iteration, we check whether any row or column indices are marked as 1 in the row[] and col[]. If yes, then we mark the current element as 0.

class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int[] rows = new int[m];
        int[] cols = new int[n];

        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(matrix[i][j]==0){
                    rows[i]=1;
                    cols[j]=1;
                }
            }
        }

        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                if(rows[i]==1 || cols[j]==1)
                    matrix[i][j] = 0;
            }
        }
    }
}

Optimal Approach - (Using Internal Space)

Instead of using extra space for 2 arrays, we directly use the internal space of the matrix to store row and column arrays. We store row array flags in the first column, matrix[i][0], and column array flags in the first row, matrix[0][j]. However, taking the first column and first row leads to a common element issue. To address this problem, we introduce one additional variable, assigning it to the first row, and assign matrix[0][0] to the first column.

Note that the flag will be marked as 0 if we encounter a 0 at a particular index (i, j) of the matrix.

We then iterate through the matrix, marking the flags in the first column for row indices and in the first row for column indices. Later, we iterate over the matrix again, filling in 0's according to the flags but excluding the first row and first column because these flags change if we include them.

Afterward, we fill in 0's for the first row by checking the flag in the first element in the first column, matrix[0][0], as it contains the flag for rows. Following this, we fill in the first column with col0 flag if it is 0.

Time - O(mxn)

Space - O(1)

class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;

        int col0 = 1;

        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(matrix[i][j]==0){
                    matrix[i][0] = 0;
                    if(j!=0){
                        matrix[0][j] = 0;
                    }
                    else{
                        col0 = 0;
                    }
                }
            }
        }

        for(int i=1; i<m; i++){
            for(int j=1; j<n; j++){
                if(matrix[i][0]==0 || matrix[0][j]==0){
                    matrix[i][j] = 0;
                }
            }
        }

        if(matrix[0][0]==0){
            for(int j=0; j<n; j++){
                matrix[0][j] = 0;
            }
        }

        if(col0==0){
            for(int i=0; i<m; i++){
                matrix[i][0] = 0;
            }
        }
    }
}