Set Matrix Zeros
Use the matrix's own first row and column as zero-flag storage to achieve O(1) extra space.
5 min read
matrix in-place
Problem#
Given an m x n matrix, if any element is 0, set its entire row and column to 0 — in place.
Examples#
[[1,1,1],[1,0,1],[1,1,1]]→[[1,0,1],[0,0,0],[1,0,1]][[0,1,2,0],[3,4,5,2],[1,3,1,5]]→[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
Constraints#
m == matrix.length,n == matrix[0].length,1 <= m, n <= 200,-2^31 <= matrix[i][j] <= 2^31 - 1.
Approach#
Reserve two scalars: whether the first row and first column themselves should be zeroed. Then walk the inner cells; whenever matrix[i][j] == 0, mark matrix[i][0] and matrix[0][j]. In a second pass, zero out cells whose row or column flag is 0. Finally apply the saved scalars to the first row/column.
Solution#
class Solution {public: void setZeroes(vector<vector<int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); bool firstRowZero = false, firstColZero = false; for (int j = 0; j < n; ++j) if (matrix[0][j] == 0) firstRowZero = true; for (int i = 0; i < m; ++i) if (matrix[i][0] == 0) firstColZero = true; for (int i = 1; i < m; ++i) for (int j = 1; j < n; ++j) if (matrix[i][j] == 0) matrix[i][0] = matrix[0][j] = 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 (firstRowZero) for (int j = 0; j < n; ++j) matrix[0][j] = 0; if (firstColZero) for (int i = 0; i < m; ++i) matrix[i][0] = 0; }};func setZeroes(matrix [][]int) { m, n := len(matrix), len(matrix[0]) firstRowZero, firstColZero := false, false for j := 0; j < n; j++ { if matrix[0][j] == 0 { firstRowZero = true } } for i := 0; i < m; i++ { if matrix[i][0] == 0 { firstColZero = true } } for i := 1; i < m; i++ { for j := 1; j < n; j++ { if matrix[i][j] == 0 { matrix[i][0] = 0 matrix[0][j] = 0 } } } for i := 1; i < m; i++ { for j := 1; j < n; j++ { if matrix[i][0] == 0 || matrix[0][j] == 0 { matrix[i][j] = 0 } } } if firstRowZero { for j := 0; j < n; j++ { matrix[0][j] = 0 } } if firstColZero { for i := 0; i < m; i++ { matrix[i][0] = 0 } }}from typing import List
class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: m, n = len(matrix), len(matrix[0]) first_row_zero = any(matrix[0][j] == 0 for j in range(n)) first_col_zero = any(matrix[i][0] == 0 for i in range(m)) for i in range(1, m): for j in range(1, n): if matrix[i][j] == 0: matrix[i][0] = 0 matrix[0][j] = 0 for i in range(1, m): for j in range(1, n): if matrix[i][0] == 0 or matrix[0][j] == 0: matrix[i][j] = 0 if first_row_zero: for j in range(n): matrix[0][j] = 0 if first_col_zero: for i in range(m): matrix[i][0] = 0function setZeroes(matrix) { const m = matrix.length, n = matrix[0].length; let firstRowZero = false, firstColZero = false; for (let j = 0; j < n; j++) if (matrix[0][j] === 0) firstRowZero = true; for (let i = 0; i < m; i++) if (matrix[i][0] === 0) firstColZero = true; for (let i = 1; i < m; i++) { for (let j = 1; j < n; j++) { if (matrix[i][j] === 0) { matrix[i][0] = 0; matrix[0][j] = 0; } } } for (let i = 1; i < m; i++) { for (let j = 1; j < n; j++) { if (matrix[i][0] === 0 || matrix[0][j] === 0) matrix[i][j] = 0; } } if (firstRowZero) for (let j = 0; j < n; j++) matrix[0][j] = 0; if (firstColZero) for (let i = 0; i < m; i++) matrix[i][0] = 0;}class Solution { public void setZeroes(int[][] matrix) { int m = matrix.length, n = matrix[0].length; boolean firstRowZero = false, firstColZero = false; for (int j = 0; j < n; j++) if (matrix[0][j] == 0) firstRowZero = true; for (int i = 0; i < m; i++) if (matrix[i][0] == 0) firstColZero = true; for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { if (matrix[i][j] == 0) { matrix[i][0] = 0; matrix[0][j] = 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 (firstRowZero) for (int j = 0; j < n; j++) matrix[0][j] = 0; if (firstColZero) for (int i = 0; i < m; i++) matrix[i][0] = 0; }}function setZeroes(matrix: number[][]): void { const m = matrix.length, n = matrix[0].length; let firstRowZero = false, firstColZero = false; for (let j = 0; j < n; j++) if (matrix[0][j] === 0) firstRowZero = true; for (let i = 0; i < m; i++) if (matrix[i][0] === 0) firstColZero = true; for (let i = 1; i < m; i++) { for (let j = 1; j < n; j++) { if (matrix[i][j] === 0) { matrix[i][0] = 0; matrix[0][j] = 0; } } } for (let i = 1; i < m; i++) { for (let j = 1; j < n; j++) { if (matrix[i][0] === 0 || matrix[0][j] === 0) matrix[i][j] = 0; } } if (firstRowZero) for (let j = 0; j < n; j++) matrix[0][j] = 0; if (firstColZero) for (let i = 0; i < m; i++) matrix[i][0] = 0;}Editorial#
Reusing the first row and column as flag storage eliminates the O(m + n) extra arrays. We must process flags before zeroing them; otherwise an original zero in column 0 contaminates flags we’re still reading.
Complexity#
- Time: O(m*n).
- Space: O(1).
Concept revision#
Related#