The given solution implements an efficient algorithm to find the maximum rectangular area in a histogram, represented by an array of heights. Let's break down how this algorithm works and why it’s efficient.
Problem Explanation
In the problem, you're given an array array that represents the heights of bars in a histogram. Your goal is to find the largest rectangular area that can be formed using these bars. A rectangle can extend as far left and right as the heights of the bars allow.
Algorithm Overview
The algorithm uses a stack to keep track of the indices of the bars in the histogram. It proceeds to compute the area of rectangles formed by each bar, ensuring that the height of the rectangle is determined by the shortest bar in the selected range.
Steps of the Solution
-
Initialization:
- A stack is created to store the indices of the histogram bars.
max_areais initialized to 0 for tracking the maximum area found.
-
Iterating through the bars:
- The algorithm iterates through each bar in the histogram.
- If the current bar is taller than the bar represented by the index at the top of the stack (or if the stack is empty), the index of the current bar is pushed onto the stack.
- If the current bar is shorter, it means we've found a boundary for the rectangles formed by the bars represented in the stack:
- The top index is popped from the stack to consider it as the smallest (or minimum height) bar for calculating the area.
- The width of the rectangle is determined by the index of the current bar and the top of the stack (after popping). If there’s no bar left in the stack, it spans to the start.
-
Calculating Remaining Areas:
- After processing all bars, any remaining indices in the stack are processed. These represent bars for which we can still compute potential areas extending to the end of the histogram.
-
Return the Result:
- The maximum area found during the iterations is returned.
Implementation of the Solution
Here's the full implementation followed by test cases to validate the solution:
def solution(n, array):
stack = []
max_area = 0
index = 0
while index < n:
# If this bar is higher than the bar at stack top, push it to the stack
if not stack or array[index] >= array[stack[-1]]:
stack.append(index)
index += 1
else:
# Pop the top
top_of_stack = stack.pop()
# Calculate the area with array[top_of_stack] as the smallest (or minimum height) bar
area = (array[top_of_stack] *
((index - stack[-1] - 1) if stack else index))
# Update max area, if needed
max_area = max(max_area, area)
# Now pop the remaining bars from stack and calculate area
while stack:
top_of_stack = stack.pop()
area = (array[top_of_stack] *
((index - stack[-1] - 1) if stack else index))
max_area = max(max_area, area)
return max_area
if __name__ == "__main__":
# Add your test cases here
print(solution(5, [1, 2, 3, 4, 5]) == 9) # Max area is 9 (3 height, width 3)
print(solution(5, [5, 6, 2, 4, 5]) == 12) # Max area is 12 (4 height, width 3)
print(solution(3, [2, 1, 5]) == 5) # Max area is 5 (5 height, width 1)
print(solution(6, [1, 2, 3, 4, 5, 6]) == 12) # Max area is 12 (4 height, width 3)
print(solution(4, [1, 1, 1, 1]) == 4) # Max area is 4 (1 height, width 4)
Complexity Analysis
- Time Complexity: O(n), where n is the number of bars. Each bar is pushed and popped from the stack at most once.
- Space Complexity: O(n) in the worst case for the stack.
This solution is efficient and robust for finding the largest rectangle in a histogram, handling various input arrays gracefully.