Discover how a simple stack can turn a huge guessing game into a quick, exact answer!
Why Largest Rectangle in Histogram Using Stack in DSA Rust?
Imagine you have a row of buildings with different heights, and you want to find the largest flat area you can cover by choosing some consecutive buildings. Doing this by checking every possible group of buildings one by one is like trying to find a needle in a haystack by looking at every straw.
Manually checking all groups of buildings is very slow and tiring. It takes a lot of time because you have to look at many combinations, and it's easy to make mistakes counting or missing some groups. This method does not work well when there are many buildings.
Using a stack helps keep track of building heights in a smart way. It lets you quickly find the largest rectangle by remembering where heights start and end without checking every group. This method is fast and avoids repeated work, making the problem easy to solve even for many buildings.
fn largest_rectangle_manual(heights: &[i32]) -> i32 {
let mut max_area = 0;
for start in 0..heights.len() {
let mut min_height = i32::MAX;
for end in start..heights.len() {
min_height = min_height.min(heights[end]);
let area = min_height * (end - start + 1) as i32;
if area > max_area {
max_area = area;
}
}
}
max_area
}fn largest_rectangle_stack(heights: &[i32]) -> i32 {
let mut stack = Vec::new();
let mut max_area = 0;
for (index, &height) in heights.iter().enumerate() {
while let Some(&top) = stack.last() {
if heights[top] > height {
let height_top = heights[stack.pop().unwrap()];
let width = if let Some(&new_top) = stack.last() {
index - new_top - 1
} else {
index
};
max_area = max_area.max(height_top * width as i32);
} else {
break;
}
}
stack.push(index);
}
let length = heights.len();
while let Some(top) = stack.pop() {
let height_top = heights[top];
let width = if let Some(&new_top) = stack.last() {
length - new_top - 1
} else {
length
};
max_area = max_area.max(height_top * width as i32);
}
max_area
}This method makes it possible to quickly find the largest rectangle in a histogram, even when there are thousands of buildings, without wasting time checking every possibility.
Think of a city planner who wants to find the biggest flat area to build a park between tall buildings. Using this method, they can quickly decide where to place the park without measuring every possible space.
Manually checking all rectangles is slow and error-prone.
Using a stack tracks building heights efficiently.
This approach finds the largest rectangle quickly and correctly.
Practice
Solution
Step 1: Understand stack usage in the problem
The stack stores indices of bars in increasing height order to find boundaries for rectangles.Step 2: Explain why this helps
This allows quick calculation of largest rectangle areas when a smaller height bar is found.Final Answer:
To keep track of bars' indices with increasing heights -> Option DQuick Check:
Stack tracks indices with increasing heights = C [OK]
- Thinking stack sorts bars by height
- Using stack to store areas directly
- Ignoring the order of bars in stack
Solution
Step 1: Identify correct stack type for indices
Indices are usize type, so stack must be Vec<usize>.Step 2: Check mutability and initialization
Stack must be mutable and initialized empty with Vec::new().Final Answer:
let mut stack: Vec<usize> = Vec::new(); -> Option AQuick Check:
Mutable Vec of usize initialized empty = B [OK]
- Using wrong type like i32 for indices
- Not making stack mutable
- Using Vec::with_capacity(0) without mut
fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut stack: Vec<usize> = Vec::new();
let mut max_area = 0;
let mut i = 0;
while i <= heights.len() {
let h = if i == heights.len() { 0 } else { heights[i] };
if stack.is_empty() || h >= heights[*stack.last().unwrap()] {
stack.push(i);
i += 1;
} else {
let top = stack.pop().unwrap();
let width = if stack.is_empty() { i } else { i - stack.last().unwrap() - 1 };
max_area = max_area.max(heights[top] * width as i32);
}
}
max_area
}
fn main() {
println!("{}", largest_rectangle_area(vec![2, 1, 5, 6, 2, 3]));
}Solution
Step 1: Trace stack and area calculation
For heights [2,1,5,6,2,3], largest rectangle area is 10 (from bars 5 and 6 with width 2).Step 2: Confirm max_area value
Code correctly calculates max_area as 10 after processing all bars.Final Answer:
10 -> Option BQuick Check:
Largest rectangle area = 10 [OK]
- Confusing max area with sum of heights
- Miscomputing width when popping stack
- Forgetting to add sentinel zero height
fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut stack: Vec<usize> = Vec::new();
let mut max_area = 0;
let mut i = 0;
while i < heights.len() {
if stack.is_empty() || heights[i] >= heights[*stack.last().unwrap()] {
stack.push(i);
i += 1;
} else {
let top = stack.pop().unwrap();
let width = if stack.is_empty() { i } else { i - stack.last().unwrap() - 1 };
max_area = max_area.max(heights[top] * width as i32);
}
}
max_area
}Solution
Step 1: Identify width calculation error
Width should be i - stack.last().unwrap() - 1 to exclude the popped bar's index.Step 2: Explain fix impact
Without subtracting 1, width is overcounted, causing wrong area calculation.Final Answer:
Subtract 1 from width calculation: i - stack.last().unwrap() - 1 -> Option AQuick Check:
Correct width calculation subtracts 1 [OK]
- Missing -1 in width calculation
- Not handling sentinel zero height
- Incorrect while loop condition
Solution
Step 1: Use stack to track indices with increasing heights
Push indices while heights increase; pop when current height is less to calculate areas.Step 2: Calculate largest rectangle area
Largest rectangle area is 12 (from bars at indices 2,3,4 with min height 4 and width 3).Final Answer:
12 -> Option CQuick Check:
Stack helps find max area 12 [OK]
- Calculating area without considering width correctly
- Ignoring bars after popping stack
- Not using sentinel zero height to flush stack
Ready to prove it?
Pass the test and this pattern moves unknown
