Set Matrix Zeroes

Updated on 02 July, 2025
Set Matrix Zeroes header image

Problem Statement

In the given problem, we have a matrix of integers with dimensions m x n. Our task is to modify this matrix in such a way that if any element in the matrix is 0, then all the elements in its associated row and column should be set to 0. This transformation is to be done on the same matrix which means it must be done in place, without using any additional matrices for output.

The challenge not only lies in detecting the zeroes and modifying the corresponding rows and columns but also in ensuring that the modification doesn't inadvertently affect the process itself, as updating once could change the matrix prematurely.

Examples

Example 1

Input:

matrix = [[1,1,1],[1,0,1],[1,1,1]]

Output:

[[1,0,1],[0,0,0],[1,0,1]]

Example 2

Input:

matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]

Output:

[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

Constraints

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -231 <= matrix[i][j] <= 231 - 1

Approach and Intuition

To tackle this problem, the solution should efficiently navigate through the matrix to identify the locations of the zeros and then mark their respective rows and columns. The key is to achieve this without additional space proportional to the size of the matrix, which calls for clever use of the matrix itself to store the state information. Here’s a breakdown of how this can be approached:

  1. Traverse the matrix to identify which rows and columns contain zeros.

    • This can be achieved by using the first row and the first column as indicators. If a row needs to be marked zeros, store this information in its corresponding element in the first column, and similarly use the elements of the first row to indicate the columns.
  2. To avoid losing the data in the first row and the first column, use two variables to keep track if the original first row or first column had any zeros.

  3. Start marking the internal cells only (skip the first row and first column), based on the state stored in the first row and the first column. By this point, modify the matrix safely assuming the marking won't prematurely affect other cells that are yet to be evaluated.

  4. After all internal marking is done, use the information in the record variables to finally resolve the first row and the first column.

  5. Scan through the first row. If it needs to be zeroed (based on the saved state), set all its elements to zero.

  6. Similarly, modify the first column if required as per the saved state.

With constraints ensuring the bounds for m and n are within manageable limits (up to 200), this approach comfortably works within a reasonable time, while adhering to the in-place requirement thus minimizing additional space use - crucial, given the limitation set by the problem statement.

Solutions

  • C++
  • Java
  • C
  • JavaScript
  • Python
cpp
class Solution {
public:
    void modifyMatrix(vector<vector<int>>& grid) {
        bool firstColumn = false;
        int totalRows = grid.size();
        int totalCols = grid[0].size();
    
        for (int row = 0; row < totalRows; row++) {
            if (grid[row][0] == 0) {
                firstColumn = true;
            }
            for (int col = 1; col < totalCols; col++) {
                if (grid[row][col] == 0) {
                    grid[0][col] = 0;
                    grid[row][0] = 0;
                }
            }
        }
    
        for (int row = 1; row < totalRows; row++) {
            for (int col = 1; col < totalCols; col++) {
                if (grid[row][0] == 0 || grid[0][col] == 0) {
                    grid[row][col] = 0;
                }
            }
        }
    
        if (grid[0][0] == 0) {
            for (int col = 0; col < totalCols; col++) {
                grid[0][col] = 0;
            }
        }
    
        if (firstColumn) {
            for (int row = 0; row < totalRows; row++) {
                grid[row][0] = 0;
            }
        }
    }
};

This solution presented in C++ provides an efficient way to set matrix zeroes for a given 2D vector grid. The problem aims to convert all elements in a row and column to zeroes if any element in that row or column is zero, effectively modifying the entire matrix based on zero presence.

  • Start by initializing a boolean firstColumn to false for tracking if the first column contains zero, needing special handling.

  • Utilize two nested loop structures:

    • The first to determine which rows and columns should be zeroed. The outer loop iterates rows, and the inner loop processes columns excluding the first one (beginning from index 1) to mark rows and columns using the first row and column of each.
    • The second to actually set the elements to zero based on the marks stored in the first row and the first column. Both row and column start from index 1 to skip initial positions already utilized as markers.
  • Handle specific edge cases:

    • If the element at grid[0][0] is zero, zero-out the entire first row.
    • If firstColumn is true (indicating the first column should be zeroed), iterate over each row and set the first column element to zero.

The algorithm efficiently marks necessary cells without using auxiliary space other than for flags (firstColumn), using the matrix itself for storage. Each element of the matrix is visited a limited number of times, leading to a time complexity that is linear relative to the size of the matrix, specifically O(m*n), where m is the number of rows and n is the number of columns.

java
class Solution {
    public void modifyMatrix(int[][] grid) {
        boolean zeroColumn = false;
        int rows = grid.length;
        int cols = grid[0].length;
    
        for (int i = 0; i < rows; i++) {
            if (grid[i][0] == 0) zeroColumn = true;
    
            for (int j = 1; j < cols; j++) {
                if (grid[i][j] == 0) {
                    grid[0][j] = 0;
                    grid[i][0] = 0;
                }
            }
        }
    
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                if (grid[i][0] == 0 || grid[0][j] == 0) {
                    grid[i][j] = 0;
                }
            }
        }
    
        if (grid[0][0] == 0) {
            for (int j = 0; j < cols; j++) {
                grid[0][j] = 0;
            }
        }
    
        if (zeroColumn) {
            for (int i = 0; i < rows; i++) {
                grid[i][0] = 0;
            }
        }
    }
}

The Java solution provided manages the task of setting matrix zeroes. It effectively uses the first row and first column of a 2D array as markers to determine which rows and columns should be zeroed out based on the presence of zeroes in the matrix. This approach ensures a space-efficient algorithm since no additional storage is required beyond the matrix itself.

  • Start by determining if the first column needs to be zeroed out entirely by checking each element of the first column. Store this determinant in a boolean variable.
  • Use nested loops to traverse each element of the matrix starting from the second row and second column, marking the respective first row and first column element zero if a zero is encountered.
  • Iterate again over the matrix (excluding the first row and column), setting an element to zero if either its respective first row or first column is marked as zero.
  • If the first element (top-left corner) of the matrix is zero, set the entire first row to zero.
  • If the first column needs to be zeroed (as determined earlier), set the entire first column to zero.

This solution methodically sets the required matrix elements to zero without using extra space proportional to the size of the matrix, which is often a key consideration for efficiency in memory usage.

c
void zeroMatrix(int** grid, int gridSize, int* gridColSize) {
    _Bool firstColZero = 0;
    int rows = gridSize;
    int cols = gridColSize[0];
    for (int i = 0; i < rows; i++) {
        if (grid[i][0] == 0) {
            firstColZero = 1;
        }
        for (int j = 1; j < cols; j++) {
            if (grid[i][j] == 0) {
                grid[0][j] = 0;
                grid[i][0] = 0;
            }
        }
    }
    for (int i = 1; i < rows; i++) {
        for (int j = 1; j < cols; j++) {
            if (grid[i][0] == 0 || grid[0][j] == 0) {
                grid[i][j] = 0;
            }
        }
    }
    if (grid[0][0] == 0) {
        for (int j = 0; j < cols; j++) {
            grid[0][j] = 0;
        }
    }
    if (firstColZero) {
        for (int i = 0; i < rows; i++) {
            grid[i][0] = 0;
        }
    }
}

This solution effectively sets matrix rows and columns to zero in a given 2D matrix based on the presence of zero elements. It uses a flag to check for zeros in the first column, enabling the function to modify the matrix without using extra storage.

Here's how the provided C function zeroMatrix works:

  1. Initialize a variable firstColZero to track if the first column contains any zeros initially.
  2. Determine the number of rows (rows) and columns (cols) from the input matrix dimensions.
  3. Traverse over each element in the matrix. If an element is zero, set the corresponding first row and first column entries to zero. This marks the rows and columns to be zeroed in the subsequent steps.
  4. In a second pass, iterate through the matrix starting from the second row and second column. Set elements to zero if their corresponding row or column marker in the first row or column is zero.
  5. After completing the marking, check if the first element of the matrix is zero. If true, set all elements in the first row to zero.
  6. Finally, if firstColZero was set to true, iterate through the first column and set all its entries to zero.

This approach minimizes space complexity as it uses the matrix itself to store information about which rows and columns need to be zeroed, avoiding the usage of any external storage except a few variables.

js
var zeroMatrix = function(grid) {
    let firstColHasZero = false;
    let rows = grid.length;
    let cols = grid[0].length;
    for (let i = 0; i < rows; i++) {
        if (grid[i][0] == 0) {
            firstColHasZero = true;
        }
        for (let j = 1; j < cols; j++) {
            if (grid[i][j] == 0) {
                grid[0][j] = 0;
                grid[i][0] = 0;
            }
        }
    }
    for (let i = 1; i < rows; i++) {
        for (let j = 1; j < cols; j++) {
            if (grid[i][0] == 0 || grid[0][j] == 0) {
                grid[i][j] = 0;
            }
        }
    }
    if (grid[0][0] == 0) {
        for (let j = 0; j < cols; j++) {
            grid[0][j] = 0;
        }
    }
    if (firstColHasZero) {
        for (let i = 0; i < rows; i++) {
            grid[i][0] = 0;
        }
    }
};

The JavaScript solution for setting matrix zeroes involves modifying the original matrix so that any row or column that contains a zero will have all its elements set to zero. The key steps in implementing this logic can be summarized as follows:

  1. Identify Zeros and Tag Rows and Columns:

    • Initialize a firstColHasZero flag to keep track of whether the first column needs to be zeroed.
    • Iterate through the matrix using a nested loop. When an element grid[i][j] is zero:
      • Set the first element of the row (i.e., grid[i][0]) and the first element of the column (i.e., grid[0][j]) to zero.
      • If any zero is found in the first column, set firstColHasZero to true.
  2. Set Elements to Zero based on Tags in First Row and Column:

    • Iterate through the matrix, skipping the first row and first column initially.
    • For rest of the matrix (grid[i][j] where i > 0 and j > 0), check if grid[i][0] or grid[0][j] is zero. If true, set grid[i][j] to zero.
  3. Handle First Row and First Column:

    • If the first cell of the matrix (grid[0][0]) is zero, set the entire first row to zero.
    • If firstColHasZero is true, set the entire first column to zero.

This approach efficiently marks relevant rows and columns using the first row and first column of the matrix itself, thereby eliminating the need for additional memory usage. By scanning and marking the matrix in the first pass and adjusting values in the second pass, the solution modifies the matrix in-place with optimal space utilization. Ensure careful handling of the first row and column separately as they are used for marking and can affect the correctness of the solution.

python
class Solution:
    def nullifyMatrix(self, grid: List[List[int]]) -> None:
        first_column_zero = False
        rows = len(grid)
        cols = len(grid[0])
    
        for row in range(rows):
            if grid[row][0] == 0:
                first_column_zero = True 
            for col in range(1, cols):
                if grid[row][col] == 0:
                    grid[0][col] = 0
                    grid[row][0] = 0
    
        for row in range(1, rows):
            for col in range(1, cols):
                if grid[row][0] == 0 or grid[0][col] == 0:
                    grid[row][col] = 0
    
        if grid[0][0] == 0:
            for col in range(cols):
                grid[0][col] = 0
    
        if first_column_zero:
            for row in range(rows):
                grid[row][0] = 0

In the provided Python solution for the "Set Matrix Zeroes" problem, the goal is to modify a given matrix so that if an element is 0, all the elements in its row and column are set to 0. This solution achieves the task without using additional space for storing the state of the rows and columns that need to be zeroed. Here’s a breakdown of how the solution operates:

  • Identify Zero Elements: It starts by determining which rows and columns need to be zeroed. This is accomplished by iterating through the matrix and using the first row and column as a record to mark the rows and columns that contain zeros. A separate boolean variable first_column_zero is used to specifically track whether the first column needs to be zeroed out, preserving the integrity of the marking system for other columns.

  • Apply Zeroing in Bulk:

    • Premarked rows and columns are zeroed in subsequent passes.
    • The next loop starts from the second row and column to safeguard the marks in the first row and the first column.
    • If the mark in the first cell of any row or the first row of any column is zero, that respective row or column is set to zero.
  • Handle First Row and Column:

    • If the initial saved state of first_column_zero or the value at grid[0][0] is zero, the respective column or row is then zeroed out in entirety.

The solution leverages the matrix itself to store temporary data, which optimizes space consumption, using the matrix's first row and column as storage to mark zeros, thus eliminating the need for additional space proportional to the matrix size. This clever use of in-place storage makes the solution both space-efficient and effective for large matrices.

Comments

No comments yet.