Min Stack
Problem
Simulate a stack of integers. Commands: push X, pop, top and min. Print one line per command. push prints ok. pop prints the removed value, top prints the top value and min prints the smallest value in the stack. If the stack is empty, pop, top and min print empty. min must work in O(1).
Constraints
- 1 <= commands <= 10^5
Examples
Input
push 5 push 3 min pop min
Output
ok ok 3 3 5
Solutions
Scanning the stack for the minimum costs O(n) for every min command. A second stack that stores the minimum at each level gives O(1) for all operations.
/*
* Problem : Process commands line by line.
* Input : Several lines of commands.
* Output : One result line per command.
* Approach: A stack with a helper stack.
* Time : O(1) per command
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: One stack keeps the values. A second stack keeps the smallest value seen up to each level.
static class MinStack {
private final java.util.ArrayDeque<Long> values = new java.util.ArrayDeque<>();
private final java.util.ArrayDeque<Long> minimums = new java.util.ArrayDeque<>();
void push(long value) {
values.push(value);
// Step 2: The new minimum is the smaller of the new value and the old minimum.
if (minimums.isEmpty() || value < minimums.peek()) {
minimums.push(value);
} else {
minimums.push(minimums.peek());
}
}
long pop() {
minimums.pop();
return values.pop();
}
long top() {
return values.peek();
}
long min() {
return minimums.peek();
}
boolean isEmpty() {
return values.isEmpty();
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
MinStack stack = new MinStack();
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
String[] parts = lines[i].split(" ");
// Step 3: Run the command. Push always works. The other commands need a non-empty stack.
if (parts[0].equals("push")) {
stack.push(Long.parseLong(parts[1]));
output[i] = "ok";
} else if (stack.isEmpty()) {
output[i] = "empty";
} else if (parts[0].equals("pop")) {
output[i] = String.valueOf(stack.pop());
} else if (parts[0].equals("top")) {
output[i] = String.valueOf(stack.top());
} else {
output[i] = String.valueOf(stack.min());
}
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- Where do you keep the minimum so you do not need to scan?