Optimal Grid Path Protocol 5 — Problem Statement & Solution Guide
Problem Description
You are tasked with analyzing a sequence of integer values representing the heights of vertical bars in a histogram. The goal is to determine the area of the largest rectangle that can be formed within the histogram boundaries. Each bar has a width of 1 unit, and the rectangle must be aligned with the baseline of the histogram. The height of the rectangle is determined by the shortest bar within its span. Your task is to compute the maximum possible area of such a rectangle for the given sequence of bar heights.
Input: An array heights of integers, where each element represents the height of a bar in the histogram.
Output: A single integer representing the maximum area of a rectangle that can be formed within the histogram.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Optimal Grid Path Protocol 5"
WHY DOES IT MATTER?
Monotonic stack patterns turn range‑minimum problems into constant‑time local updates, enabling linear‑time solutions for otherwise quadratic scenarios. Mastery of this pattern unlocks efficient solutions for skyline, water‑trapping, and stock‑span problems.
OPTIMIZATION CHALLENGE
The key insight is that each bar's maximal rectangle is bounded by the first shorter bar on its left and right. By maintaining a stack of increasing heights, we discover these boundaries on‑the‑fly without revisiting elements, collapsing O(n²) work into O(n).
REAL-WORLD CONNECTION
Think of a conveyor belt with packages of varying heights; the stack represents a temporary holding area where taller packages wait until a shorter one arrives, at which point you can calculate the maximum load that could have been stacked without toppling—mirroring load‑balancing decisions in distributed systems.
When coding, push a sentinel (height 0) at the end to force processing of remaining stack items; this eliminates a separate cleanup loop and reduces off‑by‑one bugs.
COMPLEXITY AT A GLANCE
O(n)O(n)Core Theory — Why This Approach?
The Largest Rectangle in a Histogram problem can be solved efficiently using a monotonic stack. The stack stores indices of bars in increasing height order; when a shorter bar is encountered, it signals that the rectangle with the height of the bar at the stack's top can no longer extend further, so we pop and compute the area using the current index as the right boundary and the new stack top as the left boundary. This yields the maximal area for each bar exactly once.
A naive approach would examine every possible pair of left and right boundaries, calculating the minimum height within each interval, leading to O(n²) time which is prohibitive for n up to 10⁵ or more. The stack method reduces the problem to a single linear pass because each bar is pushed and popped at most once, guaranteeing O(n) time while using O(n) auxiliary space for the stack.
The optimal paradigm exemplifies the power of monotonic data structures: by maintaining a sorted invariant (non‑decreasing heights), we transform a global minimum query into a local operation. This insight extends to many interval‑based problems, making the stack technique a staple in interview toolkits.
Interview Questions on This Problem
Q1How does a monotonic stack help compute the largest rectangle in O(n) time?
The stack keeps indices of bars in increasing height. When a lower bar appears, we pop higher bars, each pop gives the height of a potential rectangle and the current index as the right boundary; the new stack top provides the left boundary. Since each bar is pushed and popped once, total work is linear.
Q2Can you modify the algorithm to also return the coordinates (left, right, height) of the maximal rectangle?
Yes. While computing area during each pop, store the left index as (stack.empty()? 0 : stack.top()+1) and right index as current index‑1. Keep track of the rectangle with the maximum area and return its left, right, and height.
Q3What would be the impact on time and space complexity if you used a segment tree to query minimum heights instead of a stack?
A segment tree allows O(log n) minimum queries, leading to an O(n log n) solution when combined with divide‑and‑conquer. Space rises to O(n) for the tree, which is higher than the O(n) stack but still linear; however, the stack solution is strictly faster and simpler.
Examples
Input
heights = [2, 1, 5, 6, 2, 3]
Output
10
Explanation: The largest rectangle is formed by the bars of height 5 and 6, spanning indices 2 and 3. The height of the rectangle is 5 (the minimum of 5 and 6), and the width is 2 (the number of bars). The area is 5 * 2 = 10. Other potential rectangles, such as the one formed by the single bar of height 6 (area 6) or the bars of height 2 and 3 (area 6), are smaller.
Input
heights = [6, 6, 6, 6]
Output
24
Explanation: All bars have the same height of 6. The largest rectangle spans all four bars, with a height of 6 and a width of 4. The area is 6 * 4 = 24.
Input
heights = [1, 2, 3, 4, 5]
Output
9
Explanation: The largest rectangle is formed by the bars of height 3, 4, and 5, spanning indices 2, 3, and 4. The height of the rectangle is 3 (the minimum of 3, 4, and 5), and the width is 3 (the number of bars). The area is 3 * 3 = 9. Other potential rectangles, such as the one formed by the single bar of height 5 (area 5), are smaller.
Constraints
- 1 <= heights.length <= 10^5
- 0 <= heights[i] <= 10^9
Optimal Approach & Strategy
Maintain a monotonic increasing stack of bar indices; when a shorter bar appears, pop higher bars and compute areas using the current index as the right boundary. This ensures each bar is processed only twice, achieving O(n) time.
Brute Force Approach
Iterate over all possible left and right boundaries, compute the minimum height in each interval, and calculate the area. This requires O(n²) time because each interval is examined separately.
Verified Code Solutions
function solution(nums) {
let sum = 0;
let maxSum = 0;
for (let i = 0; i < nums.length; i++) {
sum += nums[i];
maxSum = Math.max(maxSum, sum);
}
return maxSum;
}class Solution {
public:
int solution(vector<int>& nums) {
int sum = 0;
int maxSum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
maxSum = max(maxSum, sum);
}
return maxSum;
}
};class Solution {
public int solution(int[] nums) {
int sum = 0;
int maxSum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
maxSum = Math.max(maxSum, sum);
}
return maxSum;
}
}def solution(nums):
sum = 0
max_sum = 0
for num in nums:
sum += num
max_sum = max(max_sum, sum)
return max_sumfunction solution(nums) {
let sum = 0;
let maxSum = 0;
for (let i = 0; i < nums.length; i++) {
sum += nums[i];
maxSum = Math.max(maxSum, sum);
}
return maxSum;
}Asked in Top Tech Interviews
Solve in Interative Editor
Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.