What if you could always know the smallest item instantly, no matter how many you add or remove?
Why Min Stack Design in DSA Rust?
Imagine you have a stack of books and you want to quickly find the smallest book without checking each one every time.
Manually searching for the smallest book each time is slow and tiring. You might miss the smallest one or waste time flipping through all books repeatedly.
A Min Stack keeps track of the smallest item as you add or remove books, so you always know the smallest book instantly without searching.
fn get_min(stack: &Vec<i32>) -> Option<i32> {
stack.iter().min().cloned()
}
// Need to scan entire stack every timestruct MinStack {
stack: Vec<i32>,
min_stack: Vec<i32>,
}
// min_stack always holds current minimumYou can get the smallest item in constant time while still using the stack normally.
Tracking the lowest price of stocks in a trading app while adding and removing price points quickly.
Manual search for minimum is slow and error-prone.
Min Stack stores minimums to give instant access.
Useful when you need fast minimum queries alongside stack operations.
Practice
Min Stack data structure?Solution
Step 1: Understand the Min Stack concept
A Min Stack is designed to keep track of the minimum element efficiently.Step 2: Identify the key feature
It allows retrieving the minimum element in constant time, unlike a normal stack.Final Answer:
To retrieve the minimum element in constant time -> Option AQuick Check:
Min Stack = fast minimum retrieval [OK]
- Thinking it sorts elements
- Confusing with queue behavior
- Assuming it reverses elements
stack and min_stack?Solution
Step 1: Check Rust vector syntax
Vectors in Rust are declared asVec<Type>, soVec<i32>is correct for 32-bit integers.Step 2: Validate struct field types
struct MinStack { stack: Vec<i32>, min_stack: Vec<i32> } usesVec<i32>for both fields, which is correct syntax and consistent types.Final Answer:
struct MinStack { stack: Vec<i32>, min_stack: Vec<i32> } -> Option CQuick Check:
Vec<i32> syntax = correct struct fields [OK]
- Using array syntax [i32] instead of Vec<i32>
- Omitting type parameters in Vec
- Mixing different integer types
let mut min_stack = MinStack::new();
min_stack.push(3);
min_stack.push(5);
min_stack.push(2);
min_stack.push(1);
min_stack.pop();
println!("{}", min_stack.get_min());Solution
Step 1: Trace push operations and min tracking
Push 3 (min=3), push 5 (min=3), push 2 (min=2), push 1 (min=1).Step 2: Pop removes last pushed element (1), min updates to previous min (2)
After popping 1, minimum is 2.Final Answer:
2 -> Option BQuick Check:
Pop last min updates min to 2 [OK]
- Assuming min stays 1 after pop
- Confusing push order
- Ignoring min stack update on pop
pop method and choose the correct fix:
fn pop(&mut self) {
self.stack.pop();
self.min_stack.pop();
}Solution
Step 1: Understand pop logic in Min Stack
Pop from stack always removes top element. Min stack should only pop if popped element equals current min.Step 2: Identify bug and fix
Current code pops min_stack unconditionally, which breaks min tracking. Fix is to pop min_stack only when needed.Final Answer:
Pop from min_stack only if popped element equals current min -> Option DQuick Check:
Conditional min_stack pop fixes min tracking [OK]
- Popping min_stack unconditionally
- Popping stack twice
- Not handling empty stack cases
push, pop, and get_min all in O(1) time. Which approach below correctly achieves this?Solution
Step 1: Analyze time complexity requirements
All operations must be O(1), so scanning or sorting is too slow.Step 2: Identify data structure approach
Two stacks approach keeps track of minimums efficiently by pushing current min on min_stack during push and popping accordingly.Final Answer:
Use two stacks: one for all elements, one for current minimums updated on push and pop -> Option AQuick Check:
Two stacks = O(1) min tracking [OK]
- Using scanning for min on each call
- Using queue instead of stack
- Sorting after each push
Ready to prove it?
Pass the test and this pattern moves unknown
