Asteroid Collision

Problem Link: Leetcode

Problem Statement

Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

Example 1:

input_1

Input: matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
Output: 6
Explanation: The maximal rectangle is shown in the above picture.

Example 2:

Input: matrix = [["0"]]
Output: 0

Example 3:

Input: matrix = [["1"]]
Output: 1

Constraints:

  • rows == matrix.length
  • cols == matrix[i].length
  • 1 <= row, cols <= 200
  • matrix[i][j] is '0' or '1'.

Hints

Hint 1

Each rectangle is a contiguous sequence of heights. How do we achieve a sequence of heights?

Hint 2

Given a sequence of heights, area of the rectangle is dictated by the mininum height of a sub-array.

Approach

1. Prepare the array of heights

We walk through each column and update the value of each cell with the continuous number of cells having '1' before and including the cell.

So for the following input:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

We can get a 2-D array heights as:

1 0 1 0 0
2 0 2 1 1
3 1 3 2 2
4 0 0 3 0

The code to build the heights is as follows:

for (int i = 0; i < c; i++) {
    int height = 0;
    for (int j = 0; j < r; j++) {
        if (matrix[j][i] == '1') {
            height++;
        } else {
            height = 0;
        }
        heights[j][i] = height;
    }
}

2. Find the maximum area for each row

For each row in heights, we can start with each cell and travel to the right as long as there is possible height. While traversing the row, we can calculate the area of the range at each step, which is dictated by the minimum height in the range.

We keep updating the maximum height at each step.

Code for this step is as follows:

int maxArea = 0;

for (int i = 0; i < r; i++) {
    for (int j = 0; j < c; j++) { // to give a starting min height
        int minHeight = heights[i][j];
        int l = j;
        while (l < c && heights[i][l]) {
            minHeight = min(minHeight, heights[i][l]);
            maxArea = max(maxArea, minHeight * (l - j + 1));
            l++;
        }
    }
}

The above step is of order O(M*N*N) in time complexity which is the overall time complexity of the solution.

We can optimize this by using a stack which is explained below.

Solution

Complete solution using Stack


class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int n = matrix[0].size();
        vector<int> heights(n + 1);
        int maxArea = 0;
        
        for (auto row : matrix) {
            for (int i = 0; i < n; i++) {
                heights[i] = row[i] == '1' ? heights[i] + 1 : 0;
            }
            
            stack<int> st;
            st.push(-1);
            for (int i = 0; i < n + 1; i++) {
                while (st.top() != -1 && heights[i] < heights[st.top()]) {
                    int h = heights[st.top()];
                    st.pop();
                    int w = i - st.top() - 1;
                    maxArea = max(maxArea, h * w);
                }
                st.push(i);
            }
        }
        
        return maxArea;        
    }
};

Note how the heights array is updated incrementally for each row. Also note that heights array is N+1 in size, having 0 at the end.

In this solution, at each step, we keep pushing indexes for each number.

And at each step, if the current number is smaller than the top element, we calculate the area upto that index and remove that index from the stack.

Why does this work?

Since we always have a 0 at the end, we can process all segments.

Home | © 2024 Last Updated: Mar 03, 2024
Buy Me A Coffee