Knowledge Guide
HomeDSACompany Practice

medium Remove All Ones With Row and Column Flips II

Problem Statement

Given a 0-indexed m x n binary matrix, return the minimum number of operations needed to remove all 1's from the matrix.

In one operation, you can choose any i and j such that:

and change the values of all cells in row i and column j to zero.

Examples

Example 1:

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

Example 2:

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

Example 3:

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

Try it yourself

Try solving this question here:

✅ Solution Remove All Ones With Row and Column Flips II

Problem Statement

Given a 0-indexed m x n binary matrix, return the minimum number of operations needed to remove all 1's from the matrix.

In one operation, you can choose any i and j such that:

  • 0 <= i < m
  • 0 <= j < n
  • grid[i][j] == 1

and change the values of all cells in row i and column j to zero.

Examples

Example 1:

  • Input:
[[1,0,1],
 [1,1,1],
 [0,1,0]]
  • Expected Output: 2
  • Justification: First, choose the cell [0,2], and perform operations. The matrix becomes [[0,0,0],[1,1,0],[0,1,0]]. Then, choose the middle cell [1,1]. The matrix becomes all zeros.

Example 2:

  • Input:
[[0,1,0],
 [1,1,1],
 [0,1,0]]
  • Expected Output: 1
  • Justification: A single operation on the middle cell (cell [1,1]) flips all the 1s to 0s. Thus, only 1 operation is needed.

Example 3:

  • Input:
[[1,1,0,0],
 [1,0,1,0],
 [0,1,1,0],
 [0,0,0,1]]
  • Expected Output: 3
  • Justification: Choose (0, 1), (1, 2), and (3, 3) cells respectively, and convert all values of respected columns and rows to zero.

Solution

To solve this problem, the algorithm employs a recursive depth-first search (DFS) strategy to explore all possible combinations of row and column flips that can lead to a grid with all zeros, starting from any cell containing a '1'. At each step, the algorithm considers a cell with a '1', performs a flip operation (sets all elements in its row and column to '0'), and then recursively checks if the resulting grid can be completely converted to zeros with fewer operations. The key insight here is to explore every possible path of flipping rows and columns from each '1' encountered in the grid, while simultaneously keeping track of the minimum number of flips required. This exhaustive search ensures that all configurations leading to the optimal solution are considered.

The algorithm effectively uses backtracking to undo the flip operations after each recursive call, ensuring that the grid is returned to its previous state before exploring a new path. This approach allows the algorithm to systematically explore all potential combinations of flips, ensuring that no possibility is left unexamined. By comparing the number of flips required for each valid path, the algorithm determines the minimum number of operations needed to convert the entire grid to zeros. This recursive and backtracking method provides a brute-force solution that guarantees finding the minimum number of operations required, albeit with significant computational complexity due to the exploration of all possible flip combinations.

Step-by-Step Algorithm

  1. Initialize Variables: Start with variables to track the minimum number of flips required (minFlips), and arrays to temporarily store the values of a row and a column being flipped (rowValues and colValues).
  2. Iterate Over Grid: Loop through each cell of the grid. For each cell containing a '1', perform the following steps:
    • Preserve Column Values: Save the current values of the column containing the '1' into colValues, and set all its elements to '0'.
    • Preserve Row Values: Similarly, save the current values of the row containing the '1' into rowValues, and set all its elements to '0'.
    • Recursive Call: Recursively call the removeOnes method on the modified grid to find the number of additional flips needed. Add 1 to this number to account for the current flip operation.
    • Track Minimum Flips: Update minFlips with the minimum between its current value and the result of the recursive call.
    • Backtrack: Restore the original values of the row and column from rowValues and colValues to backtrack before moving to the next cell. This step ensures the grid is returned to its state before the flip operation for accurate further exploration.
  3. Base Case and Return: If the function encounters a grid with no '1's (implicitly checked by not finding any '1' during the iteration), it means the grid is already all zeros, and no further operations are needed. In this case, or after exploring all cells, return the minimum number of flips found. If minFlips remains unchanged (i.e., Integer.MAX_VALUE), it indicates that no flips were needed, and the function returns 0.

Algorithm Walkthrough

Given the input grid [[1,0,1], [1,1,1], [0,1,0]], we'll walk through the algorithm step-by-step, including backtracking steps. The goal is to find the minimum number of operations needed to convert all '1's to '0's by flipping all elements in any row or column containing a '1'.

Initial Setup

Input grid:

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

Step-by-Step Walkthrough

  1. Start with the first cell (0,0) containing '1':

    • Preserve column and row before flipping:
      • Column before flip: 1,1,0 (Column 0)
      • Row before flip: 1,0,1 (Row 0)
    • Perform flip operation:
      • New grid after flip: [[0,0,0], [0,1,1], [0,1,0]]
    • Recursive call with the new grid.
  2. Recursive call depth 1:

    • The grid now looks like: [[0,0,0], [0,1,1], [0,1,0]]
    • Move to the next cell with '1', which is (1,1):
      • Preserve column and row before flipping:
        • Column before flip: 0,1,1 (Column 1)
        • Row before flip: 0,1,1 (Row 1)
      • Perform flip operation:
        • New grid after flip: [[0,0,0], [0,0,0], [0,0,0]]
      • Recursive call with the new grid.
  3. Recursive call depth 2 (Base Case Reached):

    • The grid is now all zeros: [[0,0,0], [0,0,0], [0,0,0]]
    • Since the grid is all zeros, no further operations are needed. Return 0 + current operation count (2).
    • minFlips = 1 + min(INT_MAX, 1) = 2.
  4. Backtrack from depth 2 to depth 1:

    • Restore the grid to the state before the last flip operation:
      • Grid before backtrack: [[0,0,0], [0,0,0], [0,0,0]]
      • Grid after backtrack: [[0,0,0], [0,1,1], [0,1,0]]
    • Continue exploring other possibilities, although, in this case, all '1's have been flipped already.
  5. Move to the next cell with '1', which is at (1,2):

    • Preserve column and row before flipping:
      • Column before flip: 0,1,0 (Column 2)
      • Row before flip: 0,1,1 (Row 1)
    • Perform flip operation:
      • New grid after flip: [[0,0,0], [0,0,0], [0,1,0]]
    • Recursive call with the new grid.
  6. Recursive call depth 1 for cell (1,2):

    • The grid now looks like: [[0,0,0], [0,0,0], [0,1,0]]
    • Move to the next '1', which is at (2,1). It returns 1 operation.
  7. Backtrack from depth 3 to depth 1:

    • Restore the grid to the state before the last flip operation:
      • Grid before backtrack: [[0,0,0], [0,0,0], [0,0,0]]
      • Grid after backtrack: [[0,0,0], [0,1,1], [0,1,0]]
    • minFlips = 1 + min(1, 2) = 2.
  8. Explore (2, 1) at depth 1:

  • minFlips = 1 + min(1, 2) = 2.
  1. Keep exploring other points at depth 1.

  2. Final result We need to perform minimum 2 operations to flip al 1's to 0 according to the given rules.

Code

java
public class Solution {

  public int removeOnes(int[][] grid) {
    int rows = grid.length, cols = grid[0].length;
    int minFlips = Integer.MAX_VALUE;

    int[] rowValues = new int[cols];
    int[] colValues = new int[rows];

    for (int row = 0; row < rows; row++) {
      for (int col = 0; col < cols; col++) {
        if (grid[row][col] == 0) {
          continue;
        }
        // Preserve the column values
        for (int r = 0; r < rows; r++) {
          colValues[r] = grid[r][col];
          grid[r][col] = 0;
        }
        // Preserve the row values
        for (int c = 0; c < cols; c++) {
          rowValues[c] = grid[row][c];
          grid[row][c] = 0;
        }
        // Recurse
        minFlips = Math.min(minFlips, (1 + removeOnes(grid)));

        // Backtrack
        // Since we preserved the row values later, so we but them back first
        for (int c = 0; c < cols; c++) {
          grid[row][c] = rowValues[c];
        }
        // Since we preserved the col values first, so we put them back later
        for (int r = 0; r < rows; r++) {
          grid[r][col] = colValues[r];
        }
      }
    }
    return ((minFlips == Integer.MAX_VALUE) ? 0 : minFlips);
  }

  public static void main(String[] args) {
    Solution solution = new Solution();

    // Test Example 1
    int[][] example1 = { { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 0 } };
    System.out.println(
      "Minimum Operations for Example 1: " + solution.removeOnes(example1)
    );

    // Test Example 2
    int[][] example2 = { { 0, 1, 0 }, { 1, 1, 1 }, { 0, 1, 0 } };
    System.out.println(
      "Minimum Operations for Example 2: " + solution.removeOnes(example2)
    );

    // Test Example 3
    int[][] example3 = {
      { 1, 1, 0, 0 },
      { 1, 0, 1, 0 },
      { 0, 1, 1, 0 },
      { 0, 0, 0, 1 },
    };
    System.out.println(
      "Minimum Operations for Example 3: " + solution.removeOnes(example3)
    );
  }
}

Complexity Analysis

Time Complexity:

  • Worst-case scenario: The algorithm iterates through every cell of the grid, attempting to flip each '1' it encounters and recursively solving the modified grid. In the worst case, this approach could explore nearly every combination of flips for a grid filled with '1's.
  • Given a grid of size (m * n), the worst-case time complexity can approach , considering each cell flip could lead to a recursive call (although not all flips will result in a recursive call due to the base case check).

Space Complexity:

  • Worst-case scenario: The recursion depth can go up to (mn) in theory, if each cell's flip leads to a unique recursive call. However, practical limits on recursion depth and the fact that many paths will be pruned early mean actual usage may be less.
  • Auxiliary space: It is used for storing the row and column values for backtracking, leading to .
  • Total Space Complexity: due to the grid copy (implicit in recursion stack) and the auxiliary space for row and column preservation during backtracking.
🤖 Don't fully get this? Learn it with Claude

Stuck on Remove All Ones With Row and Column Flips II? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Remove All Ones With Row and Column Flips II** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Remove All Ones With Row and Column Flips II** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Remove All Ones With Row and Column Flips II**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Remove All Ones With Row and Column Flips II**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes