Largest Rectangle in Histogram Using Stack in DSA C++ - Time & Space Complexity
We want to understand how the time needed to find the largest rectangle in a histogram changes as the number of bars grows.
How does the algorithm's speed change when the histogram size increases?
Analyze the time complexity of the following code snippet.
int largestRectangleArea(vector<int>& heights) {
stack<int> s;
int maxArea = 0;
int i = 0;
while (i < heights.size()) {
if (s.empty() || heights[i] >= heights[s.top()]) {
s.push(i++);
} else {
int top = s.top(); s.pop();
int area = heights[top] * (s.empty() ? i : i - s.top() - 1);
maxArea = max(maxArea, area);
}
}
while (!s.empty()) {
int top = s.top(); s.pop();
int area = heights[top] * (s.empty() ? i : i - s.top() - 1);
maxArea = max(maxArea, area);
}
return maxArea;
}
This code finds the largest rectangle area in a histogram by using a stack to track bars and calculate areas efficiently.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loops that push and pop indices from the stack while scanning the histogram bars.
- How many times: Each bar is pushed and popped at most once, so operations repeat roughly 2n times for n bars.
As the number of bars increases, the total operations grow roughly in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 stack operations |
| 100 | About 200 stack operations |
| 1000 | About 2000 stack operations |
Pattern observation: The operations grow linearly with input size, roughly doubling the number of bars.
Time Complexity: O(n)
This means the time to find the largest rectangle grows in a straight line with the number of bars in the histogram.
[X] Wrong: "The nested while loops make this algorithm O(n²) because it looks like two loops inside each other."
[OK] Correct: Each bar is pushed and popped only once, so the total operations add up to about 2n, not n squared.
Understanding this linear time stack approach shows you can solve tricky problems efficiently, a skill valued in many coding challenges.
"What if we used a simple nested loop to check all rectangles instead of a stack? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of stack in the problem
The stack is used to store indices of bars in increasing order of their heights to efficiently calculate areas.Step 2: Why increasing order indices?
When a bar with smaller height is found, we pop from the stack to calculate the largest rectangle possible with the popped bar as the smallest height.Final Answer:
To keep track of indices of bars with increasing heights -> Option AQuick Check:
Stack stores indices in increasing height order = A [OK]
- Thinking stack stores heights instead of indices
- Assuming stack sorts bars by height
- Using stack to count bars instead of tracking indices
Solution
Step 1: Check correct stack declaration syntax in C++
The correct way to declare an empty stack of integers isstack<int> s;.Step 2: Identify errors in other options
stack<int> s = new stack<int>(); uses 'new' which is incorrect for stack initialization. stack s<int>; has wrong template syntax. stack<int> s[]; declares an array of stacks, not a single stack.Final Answer:
stack<int> s; -> Option CQuick Check:
Correct stack declaration = C [OK]
- Using 'new' keyword incorrectly with stack
- Wrong template syntax like stack s<int>
- Declaring array of stacks instead of single stack
int largestRectangleArea(vector<int>& heights) {
stack<int> s;
int max_area = 0, i = 0;
while (i < heights.size()) {
if (s.empty() || heights[i] >= heights[s.top()]) {
s.push(i++);
} else {
int tp = s.top(); s.pop();
int area = heights[tp] * (s.empty() ? i : i - s.top() - 1);
max_area = max(max_area, area);
}
}
while (!s.empty()) {
int tp = s.top(); s.pop();
int area = heights[tp] * (s.empty() ? i : i - s.top() - 1);
max_area = max(max_area, area);
}
return max_area;
}
cout << largestRectangleArea({2,1,5,6,2,3});Solution
Step 1: Trace the stack operations and area calculations
For heights [2,1,5,6,2,3], the largest rectangle area is 10 (from bars 5 and 6 with width 2).Step 2: Confirm final max_area value
After processing all bars and stack cleanup, max_area is 10.Final Answer:
10 -> Option BQuick Check:
Largest rectangle area = 10 [OK]
- Miscomputing width when popping from stack
- Forgetting to process remaining stack after loop
- Mixing up indices and heights in area calculation
int largestRectangleArea(vector<int>& heights) {
stack<int> s;
int max_area = 0, i = 0;
while (i < heights.size()) {
if (s.empty() || heights[i] >= heights[s.top()]) {
s.push(i++);
} else {
int tp = s.top(); s.pop();
int area = heights[tp] * (s.empty() ? i : i - s.top() - 1);
max_area = max(max_area, area);
}
}
while (!s.empty()) {
int tp = s.top(); s.pop();
int area = heights[tp] * (s.empty() ? i : i - s.top() - 1);
max_area = max(max_area, area);
}
return max_area;
}Solution
Step 1: Analyze width calculation formula
The width should bei - s.top() - 1but code usesi - s.top(), missing the '-1'.Step 2: Effect of missing '-1'
This causes overestimation of width and incorrect area calculation.Final Answer:
Width calculation misses subtracting 1 from index difference -> Option AQuick Check:
Width = i - s.top() - 1 needed [OK]
- Using i - s.top() instead of i - s.top() - 1
- Not incrementing i in else block (but here it is correct)
- Wrong comparison operator in if condition
Solution
Step 1: Use stack to track indices of increasing heights
Push indices while heights increase: indices 0(6), then 1(2) triggers pop of 0, area=6*1=6. Continue pushing and popping to calculate areas.Step 2: Calculate max area by popping stack when current height is less
Largest rectangle area found is 15 (from bars at indices 2,3,4 with min height 5 and width 3).Final Answer:
15 -> Option DQuick Check:
Largest rectangle area = 15 [OK]
- Not popping stack correctly when height decreases
- Incorrect width calculation during area computation
- Ignoring last stack cleanup after main loop
Ready to prove it?
Pass the test and this pattern moves unknown
