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: 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.lengthcols == matrix[i].length1 <= row, cols <= 200matrix[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.
