Largest Submatrix With Rearrangements

Updated on 04 June, 2025
Largest Submatrix With Rearrangements header image

Problem Statement

In this challenge, you are provided with a binary matrix of dimensions m x n. The cells of the matrix contain either a 0 or a 1. Your task is to find the largest possible area of a contiguous submatrix that consists entirely of 1s after potentially reordering the columns of the given matrix. This problem checks your ability to manipulate column positions to maximize the area of contiguous 1s vertically aligned. Finding the optimal column arrangement that produces the submatrix with the maximum area of 1s is crucial to solving this problem efficiently.

Examples

Example 1

Input:

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

Output:

4

Explanation:

You can rearrange the columns as shown above.
The largest submatrix of 1s, in bold, has an area of 4.

Example 2

Input:

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

Output:

3

Explanation:

You can rearrange the columns as shown above.
The largest submatrix of 1s, in bold, has an area of 3.

Example 3

Input:

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

Output:

2

Explanation:

Notice that you must rearrange entire columns, and there is no way to make a submatrix of 1s larger than an area of 2.

Constraints

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m * n <= 105
  • matrix[i][j] is either 0 or 1.

Approach and Intuition

  1. Understanding the Matrix Configuration:

    • The matrix configuration allows for movement of columns but not individual elements within those columns. The goal is to align columns in such a way that maximizes contiguous vertical stacks of 1s.
  2. Basic Idea:

    • Imagine 'compressing' the matrix downwards by turning columns such that all 1s in each column stack together at the bottom of the matrix (or the top, since the direction of compression does not necessarily matter). The task is then to line up these compressed columns to form the largest rectangle possible.
  3. Column Ranking by 1s:

    • For each column, determine how many 1s it contains. The reordering of the columns will then depend on these counts. Columns with more 1s should be adjacent to each other to form a larger contiguous submatrix of 1s when stacked.
  4. Building the Submatrix:

    • After reordering the columns by the descending count of 1s, iterate through each possible height (from 1 up to the maximum number of rows, m). For each height, calculate the potential area by multiplying the height with the number of consecutive columns that have at least that many 1s.
    • Use an efficient way to traverse and calculate the maximum area for each possible height of submatrix. This will often involve dynamic programming or a stack-based approach to efficiently compute the maximum rectangle in a histogram—a common subproblem.
  5. Evaluating the best configuration:

    • Throughout the previous step, maintain a variable to store the maximum area found. Once the iterations are completed, this value will represent the area of the largest submatrix composed only of 1s.

This problem combines concepts from several classic problems such as "Largest Rectangle in Histogram" and "Maximal Rectangle", but with an added complexity of optimally reordering columns, which turns it into a more unique and challenging problem.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int maxSubmatrix(vector<vector<int>>& grid) {
        int rows = grid.size();
        int cols = grid[0].size();
        vector<pair<int,int>> prevRows;
        int largest = 0;
        
        for (int i = 0; i < rows; i++) {
            vector<pair<int,int>> heights;
            vector<bool> checked = vector(cols, false);
            
            for (auto [existingHeight, columnIndex] : prevRows) {
                if (grid[i][columnIndex] == 1) {
                    heights.push_back({existingHeight + 1, columnIndex});
                    checked[columnIndex] = true;
                }
            }
            
            for (int j = 0; j < cols; j++) {
                if (!checked[j] && grid[i][j] == 1) {
                    heights.push_back({1, j});
                }
            }
            
            for (int k = 0; k < heights.size(); k++) {
                largest = max(largest, heights[k].first * (k + 1));
            }
            
            prevRows = heights;
        }

        return largest;
    }
};

The provided solution in C++ aims to find the largest submatrix that can be formed by rearranging rows of a binary matrix. The approach used here is dynamic, utilizing the concept of "heights" where each cell's new height depends on its predecessor in the previous row. Follow these steps to understand the process:

  • Start by acquiring the size of the grid which includes the number of rows and columns.

  • Maintain a vector prevRows to hold the heights and their respective column indices from the previous row.

  • Loop over each row in the grid:

    • Initialize a vector heights for the current row to store pairs of height and column index.

    • A boolean vector checked is used to track columns that have been updated in the current row.

      • For each height and its associated column index from prevRows, check if the current grid position (grid[i][columnIndex]) is 1. If true, update the height for that column and mark it as checked.
    • Iterate through all columns in the current row. If a column isn't checked but has a 1 in the grid, then record this as a height of 1 in the heights vector for the unmatched column.

    • For the collected heights in the heights vector, calculate possible submatrix sizes and update largest to reflect the maximum submatrix area found so far using height multiplied by the row width accounted up to that column.

    • Update prevRows with the current row's heights to be used in the next iteration.

  • The value of largest at the end of the rows' processing gives the area of the largest rearrangeable submatrix.

This algorithm effectively computes the maximum area of all potential submatrices by dynamically adjusting and calculating row heights based on previous rows, making it a practical approach for handling binary matrices where rearrangement is possible. The logic mainly capitalizes on dynamic programming elements and the efficiency of vector operations in C++.

java
class Solution {
    public int maxSubmatrix(int[][] grid) {
        int rows = grid.length;
        int cols = grid[0].length;
        List<Pair<Integer,Integer>> prevRowsHeights = new ArrayList();
        int maximum = 0;
        
        for (int i = 0; i < rows; i++) {
            List<Pair<Integer,Integer>> currentHeights = new ArrayList();
            boolean[] detected = new boolean[cols];
            
            for (Pair<Integer, Integer> element : prevRowsHeights) {
                int oldHeight = element.getKey();
                int column = element.getValue();
                if (grid[i][column] == 1) {
                    currentHeights.add(new Pair(oldHeight + 1, column));
                    detected[column] = true;
                }
            }
            
            for (int j = 0; j < cols; j++) {
                if (!detected[j] && grid[i][j] == 1) {
                    currentHeights.add(new Pair(1, j));
                }
            }
            
            for (int k = 0; k < currentHeights.size(); k++) {
                maximum = Math.max(maximum, currentHeights.get(k).getKey() * (k + 1));
            }

            prevRowsHeights = currentHeights;
        }
        
        return maximum;
    }
}

In the provided Java solution, the goal is to determine the largest submatrix with possible rearrangements in a given binary grid. The solution utilizes dynamic programming and sorting techniques to efficiently solve the problem.

Here's how the algorithm is structured:

  1. The class named Solution contains a method maxSubmatrix which takes a 2D array grid as its parameter.
  2. Two integer variables, rows and cols, store the dimensions of the grid.
  3. Use a list prevRowsHeights to track the heights of consecutive 1s from previous rows.
  4. A variable maximum is initialized to zero to keep track of the maximum area found.
  5. The outer loop iterates through each row of the grid, where i is the row index.
  6. Inside each row iteration, initialize a new list currentHeights and a boolean array detected for checking columns that have been updated in the current row.
  7. Iterate through prevRowsHeights to update the height of continuous 1s.
    • If the current cell in the grid is 1, increment the height from prevRowsHeights and add to currentHeights.
    • Mark the column as detected.
  8. After processing previous heights, check all columns in the current row for any undetected columns with a 1:
    • Add these new heights to currentHeights.
  9. Calculate potential maximal rectangles using heights in currentHeights. The possible area is the height times the number of items processed up to that point.
  10. Update the maximum variable if the calculated area exceeds the current maximum.
  11. Before moving to the next row, update prevRowsHeights to currentHeights for use in next iteration.
  12. Finally, the method returns the value of maximum, representing the largest area of rearranged submatrix possible.

The algorithm efficiently keeps track of continuous vertical runs of 1s and calculates potential areas in each row by leveraging previously computed values. The implementation uses dynamic programming by reflecting previous computations to the current context, which optimizes the process by reducing redundant calculations.

python
class Solution:
    def maxSubmatrix(self, grid: List[List[int]]) -> int:
        rows = len(grid)
        cols = len(grid[0])
        heights_prev = []
        maximum = 0

        for i in range(rows):
            current_heights = []
            presence = [False] * cols

            for height, column in heights_prev:
                if grid[i][column] == 1:
                    current_heights.append((height + 1, column))
                    presence[column] = True

            for j in range(cols):
                if not presence[j] and grid[i][j] == 1:
                    current_heights.append((1, j))

            for k in range(len(current_heights)):
                maximum = max(maximum, current_heights[k][0] * (k + 1))

            heights_prev = current_heights

        return maximum

In the task to find the largest submatrix with rearrangements, the Python implementation hinges on constructing matrices based on previously computed heights coupled with the current row's cell values. This method is effective for enhancing the space complexity by avoiding the direct calculation of all potential submatrices, instead, incrementally building upon a known successful substructure.

  • Initialize the matrix dimensions and a list for previous row heights.
  • Iterate over each row to update the height of each column:
    • Utilize a presence array to track if an existing column should extend its previous height or start anew.
    • If a column contains a 1, update either its continued height from the previous row or initialize it to 1 if it's newly started.
  • For each row, compute potential submatrices' areas based on the heights at the end of that row's processing:
    • Determine the maximum area possible by considering each column's height and assuming it can extend across all previous columns in the most optimal rearrangement.
    • Update the global maximum area if a larger area is found.
  • The maximum area ultimately provides the largest rearrangeable submatrix's size following the completion of row processing.

This method reduces the computational overhead by focusing on only the essential calculations essential for determining maximum rearrangeable submatrix areas, rather than exhaustively considering all submatrices.

Comments

No comments yet.