The problem
Given an array of integers heights
representing the histogram’s bar height where the width of each bar is 1
, return the area of the largest rectangle in the histogram.
Examples
Input: heights = [2,1,5,6,2,3]
Output: 10
Explanation: The above is a histogram where width of each bar is 1.
The largest rectangle is shown in the red area, which has an area = 10 units.
Input: heights = [2,4]
Output: 4
Constraints
- 1 <= heights.length <= 10^5
- 0 <= heights[i] <= 10^4
Explanation
Before we jump to the solution, let’s visualize the problem with Input: heights = [2,1,5,6,2,3]
After we calculated the area, you can see that the largest rectangle has an area 10
.
Now let’s figure out why it works this way.
If we just draw the first two elements, we can see the pattern that with rectangle with height 2
, once we reached the 1
, we can’t extend it any further, because 1 < 2
and we have a hole.
For rectangle with value 1
, we can extend it towards the left and use the left rectangle.
Now let’s look at an example when the 1
comes first
In this case, we can keep extending it to the right because nothing is stopping us.
In case if two rectangles are even, we can extend it to the right too.
After analyzing all cases from above, we can conclude that current heights will be in increasing order.
Stack Solution
func largestRectangleArea(_ heights: [Int]) -> Int {
var maxArea = 0
var stack: [(Int, Int)] = []
for (i, h) in heights.enumerated() {
var start = i
while !stack.isEmpty && stack.last!.1 > h {
let (index, height) = stack.removeLast()
maxArea = max(maxArea, height * (i - index))
start = index
}
stack.append((start, h))
}
for (i, h) in stack {
maxArea = max(maxArea, h * (heights.count - i))
}
return maxArea
}
Explanation
To solve this problem, we will be using a stack. We will be looking for increasing heights and where increasing stopped.
If we found the rectangle that cannot be extended, we will compute the area and pop the element.
For example, input with heights = [1, 2, 3, 4, 2]
You can see that we can’t extend rectangle with value 4
any further, so we will compute the area and pop 4
.
We also cannot extend rectangle with value 3
, so we need to compute the area and pop it as well.
As for rectangle with value 2
, we can extend it because the rightmost value to it is also 2
.
So in this example, we only need to remove values 3
and 4
.
Now let’s look at the algorithm.
- We start at index
0
, and add height2
to our stack - Next, we get to index
1
, and add height1
to our stack, but you can see that we have height1
at the top of our stack, and we can’t extend area with height2
any further. The max area that we have so far istwo
, because our width isone
, and our height istwo
, and now we can pop rectangle with value2
from our stack. We can also extend rectangle at indexone
to the left, so index for this height will bezero
- Next, we are going to get to index
two
and height5
, five is greater than one and it can be extended, so we are going to add it to our stack - Next, we get to index
three
, and again, height6
is greater than5
, so we are going to add it to our stack - Next, at index
four
we have height2
, and we can’t extend previous rectangle with height6
any further, therefore we need to compute the area and pop it - Now, the top value in our stack has height
5
, and it is also greater than2
, so we need to compute the area, and pop it. As for start index for rectangle with height2
, we can extend backwards to the indextwo
, because we just popped two elements - Lastly, we reach our index
five
with height3
, so we put it into our stack, and we do not need to pop previous value2
, because3 > 2
, and we can continue extending. As for start index, we can’t extend backwards anymore so it will be5
At this point, we have three values that are still in our stack, and we need to compute areas for these heights
- At index
five
and height3
, it started and went all the way to the end of the histogram, that means that the length for it is just1
, and we can compute the area of3
. The area of3
is not greater than our current maximum of10
, so we don’t update our max - At the next index of
2
, we have height2
, so this means that the area starts from index2
, and went all the way to the end of histogram. This means that width was4
and height was2
, so the computed area equals8
. The calculated area is not greater than10
, so we don’t update our max area - At the last area of our stack with index
0
, and height1
, tells us that it started at index0
and went all the way to the end of the histogram, so the width will be6
, the height was1
, so the calculated area equals6
, this area is not greater than our current value of10
, so we do not update max area
Time/Space complexity
- Time complexity: O(n)
- Space complexity: O(n)