Remove All Ones With Row and Column Flips medium

Problem Statement

You are given a 2D integer array matrix where matrix[i][j] represents the element at the i-th row and j-th column of the matrix.

A row or column flip is an operation where you select a row or column and set all elements in that row or column to 1.

Determine whether it's possible to make all elements in the matrix equal to 1 using at most one row flip and one column flip.

Example 1

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

Output: true

Explanation: Flip the first row and the second column to make all elements equal to 1.

Example 2

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

Output: false

Explanation: It is not possible to make all elements equal to 1.

Steps and Explanation

The core idea is to analyze the possibilities efficiently. We don't need to exhaustively check all combinations of row and column flips. Instead, we can strategically focus on:

  1. Check rows first: For each row, consider what the column flips would have to be to make that row all 1s.

  2. Consistent Column Flips: If, after checking all rows, a particular column requires a flip inconsistently (i.e., sometimes needs to be flipped, sometimes doesn't), then it's impossible.

  3. No flips required: If every row already has all 1s, we're done.

  4. One row flip: If we find a scenario where a single row flip followed by consistent column flips can make everything 1s, it's true.

  5. No solution: If none of the above are true, then it's false.

Here's how we code this logic:

Code (Java)

class Solution {
    public boolean removeOnes(int[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[0].length;

        // Check if all elements are already 1
        boolean allOnes = true;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (matrix[i][j] == 0) {
                    allOnes = false;
                    break;
                }
            }
            if (!allOnes) break;
        }
        if (allOnes) return true;


        for (int i = 0; i < (1 << rows); i++) { // Iterate through possible row flips
            boolean possible = true;
            boolean[] colFlips = new boolean[cols]; // Track column flips for this row flip scenario

            for (int r = 0; r < rows; r++) {
                boolean rowFlip = (i >> r) % 2 == 1; // Check if row r needs flipping

                for (int c = 0; c < cols; c++) {
                    int val = matrix[r][c];
                    boolean shouldFlip = rowFlip ? (val == 0) : (val == 0);
                    if (shouldFlip) {
                        if (colFlips[c] == true) { // Inconsistent
                            possible = false;
                            break;
                        }
                        colFlips[c] = true;
                    }
                }
                if (!possible) break;
            }
            if (possible) return true;
        }
        return false;
    }
}

Complexity Analysis

  • Time Complexity: O(2R * R * C), where R is the number of rows and C is the number of columns. This is because we iterate through all possible row flip combinations (2R) and for each combination, we examine each cell (R * C).

  • Space Complexity: O(C), due to the colFlips boolean array which stores the column flip status for each combination. The space complexity is not dominated by the input matrix itself.