🧠
Optimal In-Place Using First Row and Column as Flags
💡 This approach cleverly uses the first row and first column of the matrix itself to store flags, eliminating extra space usage beyond two booleans. Beginners learn how to reuse input space safely.
Intuition
Use the first row and first column to mark which rows and columns should be zeroed, then update the matrix in a second pass. Use two separate booleans to track if the first row and first column originally had zeros.
Algorithm
- Check if first row has any zeros and store in a boolean.
- Check if first column has any zeros and store in a boolean.
- Use first row and column to mark zeros for other rows and columns.
- Zero out cells based on marks in first row and column.
- Finally, zero out first row and/or first column if needed.
💡 The tricky part is preserving the original first row and column zero info before overwriting them as flags.
def setZeroes(matrix):
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] = 0
# Example usage
if __name__ == '__main__':
mat = [[1,1,1],[1,0,1],[1,1,1]]
setZeroes(mat)
print(mat)
Line Notes
first_row_zero = any(matrix[0][j] == 0 for j in range(n))Check if first row contains zero before using it as flag storage
first_col_zero = any(matrix[i][0] == 0 for i in range(m))Check if first column contains zero before using it as flag storage
if matrix[i][j] == 0:Mark corresponding first row and column positions as zero flags
if matrix[i][0] == 0 or matrix[0][j] == 0:Use flags to zero out cells
if first_row_zero:Zero out first row if originally contained zero
if first_col_zero:Zero out first column if originally contained zero
public 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;
break;
}
}
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
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;
}
}
public static void main(String[] args) {
Solution sol = new Solution();
int[][] mat = {{1,1,1},{1,0,1},{1,1,1}};
sol.setZeroes(mat);
System.out.println(java.util.Arrays.deepToString(mat));
}
}
Line Notes
boolean firstRowZero = false, firstColZero = false;Track if first row or column originally had zeros
for (int j = 0; j < n; j++)Scan first row for zeros before using it as flag storage
for (int i = 0; i < m; i++)Scan first column for zeros before using it as flag storage
if (matrix[i][j] == 0)Mark first row and column to flag zero rows and columns
if (matrix[i][0] == 0 || matrix[0][j] == 0)Zero out cells based on flags
if (firstRowZero)Zero out first row if needed
if (firstColZero)Zero out first column if needed
#include <iostream>
#include <vector>
using namespace std;
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;
break;
}
}
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
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;
}
}
int main() {
vector<vector<int>> mat = {{1,1,1},{1,0,1},{1,1,1}};
setZeroes(mat);
for (auto &row : mat) {
for (auto &val : row) cout << val << ' ';
cout << '\n';
}
return 0;
}
Line Notes
bool firstRowZero = false, firstColZero = false;Booleans to remember if first row/column had zeros originally
for (int j = 0; j < n; j++)Check first row for zeros before using it as flag storage
for (int i = 0; i < m; i++)Check first column for zeros before using it as flag storage
if (matrix[i][j] == 0)Mark first row and column to indicate zero rows and columns
if (matrix[i][0] == 0 || matrix[0][j] == 0)Zero out cells based on flags
if (firstRowZero)Zero out first row if needed
if (firstColZero)Zero out first column if needed
function 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;
break;
}
}
for (let i = 0; i < m; i++) {
if (matrix[i][0] === 0) {
firstColZero = true;
break;
}
}
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;
}
}
// Example usage
const mat = [[1,1,1],[1,0,1],[1,1,1]];
setZeroes(mat);
console.log(mat);
Line Notes
let firstRowZero = false, firstColZero = false;Track if first row or column originally had zeros
for (let j = 0; j < n; j++)Scan first row for zeros before using it as flag storage
for (let i = 0; i < m; i++)Scan first column for zeros before using it as flag storage
if (matrix[i][j] === 0)Mark first row and column to flag zero rows and columns
if (matrix[i][0] === 0 || matrix[0][j] === 0)Zero out cells based on flags
if (firstRowZero)Zero out first row if needed
if (firstColZero)Zero out first column if needed
We scan the matrix a few times but only use constant extra space for two booleans.
💡 For a 200x200 matrix, this is about 80,000 operations but no extra arrays, making it space efficient.
Interview Verdict: Accepted
This is the preferred approach in interviews due to its optimal space usage and clarity once understood.