Consider a Min Stack that supports push, pop, top, and get_min operations. What is the output of the get_min calls after the following operations?
push(3)
push(5)
get_min()
push(2)
push(1)
get_min()
pop()
get_min()
pop()
top()
struct MinStack {
stack: Vec<i32>,
min_stack: Vec<i32>,
}
impl MinStack {
fn new() -> Self {
MinStack { stack: Vec::new(), min_stack: Vec::new() }
}
fn push(&mut self, val: i32) {
self.stack.push(val);
if self.min_stack.is_empty() || val <= *self.min_stack.last().unwrap() {
self.min_stack.push(val);
}
}
fn pop(&mut self) {
if let Some(top) = self.stack.pop() {
if top == *self.min_stack.last().unwrap() {
self.min_stack.pop();
}
}
}
fn top(&self) -> Option<i32> {
self.stack.last().copied()
}
fn get_min(&self) -> Option<i32> {
self.min_stack.last().copied()
}
}
fn main() {
let mut min_stack = MinStack::new();
min_stack.push(3);
min_stack.push(5);
println!("{:?}", min_stack.get_min());
min_stack.push(2);
min_stack.push(1);
println!("{:?}", min_stack.get_min());
min_stack.pop();
println!("{:?}", min_stack.get_min());
min_stack.pop();
println!("{:?}", min_stack.top());
}Track the minimum values on a separate stack and update it on push and pop.
The min stack keeps track of minimums. After pushing 3 and 5, min is 3. After pushing 2 and 1, min is 1. Popping 1 removes it from min stack, min becomes 2. Popping 2 removes it, top is 5.
Why does a Min Stack implementation typically use two stacks instead of one?
Think about how to get the minimum value quickly after each operation.
One stack stores all elements; the other keeps track of minimum values so get_min() is O(1).
What error will occur when running this pop method in a Min Stack implementation?
fn pop(&mut self) {
let top = self.stack.pop().unwrap();
if top == self.min_stack.last().unwrap() {
self.min_stack.pop();
}
}Consider what happens if pop is called when the stack is empty.
Calling unwrap() on None causes panic if stack is empty. Safe code should check before popping.
What is the output of the get_min calls after these operations on a Min Stack?
push(2)
push(2)
push(1)
push(1)
pop()
get_min()
pop()
get_min()
struct MinStack {
stack: Vec<i32>,
min_stack: Vec<i32>,
}
impl MinStack {
fn new() -> Self {
MinStack { stack: Vec::new(), min_stack: Vec::new() }
}
fn push(&mut self, val: i32) {
self.stack.push(val);
if self.min_stack.is_empty() || val <= *self.min_stack.last().unwrap() {
self.min_stack.push(val);
}
}
fn pop(&mut self) {
if let Some(top) = self.stack.pop() {
if top == *self.min_stack.last().unwrap() {
self.min_stack.pop();
}
}
}
fn get_min(&self) -> Option<i32> {
self.min_stack.last().copied()
}
}
fn main() {
let mut min_stack = MinStack::new();
min_stack.push(2);
min_stack.push(2);
min_stack.push(1);
min_stack.push(1);
min_stack.pop();
println!("{:?}", min_stack.get_min());
min_stack.pop();
println!("{:?}", min_stack.get_min());
}Remember how duplicate minimums are handled in min_stack.
After popping one '1', min is still 1 because of duplicate. After popping second '1', min becomes 2.
Which approach allows implementing a Min Stack that uses only one stack and O(1) extra space for tracking the minimum?
Think about encoding minimum information within the stack elements themselves.
Storing differences allows tracking minimum without extra stack, updating minimum on push/pop in O(1) space.
