Chapter 7: Stacks
Short Answer · The Stack ADT
Question 1: push/pop Output
What does this code print?
Deque<Integer> s = new ArrayDeque<>();
s.push(4); s.push(9); s.push(2);
System.out.print(s.pop() + " ");
s.push(7);
System.out.print(s.peek() + " ");
System.out.print(s.pop() + s.pop() + " ");
s.push(5);
System.out.print(s.size() + " " + s.peek());
Show answer
Output: 2 7 16 2 5
- 4, 9, 2 are pushed; 2 is on top, so
pop()returns 2 (LIFO). Stack (bottom→top): 4 9. - 7 is pushed;
peek()returns 7 without removing it. s.pop() + s.pop()is integer addition first: 7 + 9 = 16. Stack: 4.- 5 is pushed: the stack is 4 5 →
size()is 2,peek()is 5.
Short Answer · The Stack ADT
Question 2: An Operation Sequence and the Final Stack
These operations run in order on an empty stack. What does each pop() return? What is left on the stack at the end, and which item is on top?
push(5), push(3), pop(), push(8), push(1), pop(), pop(), push(4)
Show answer
- push(5), push(3) → [5, 3];
pop()→ 3 - push(8), push(1) → [5, 8, 1];
pop()→ 1;pop()→ 8 - push(4) → [5, 4]
The pops return 3, 1, 8. The stack ends as 5, 4 from bottom to top, with 4 on top.
Multiple Choice · The Stack ADT
Question 3: Possible Output Orders
The numbers 1, 2, 3, 4 are pushed in that order, and pop() may be called at any point in between. Which order of popped values is impossible?
C: if 4 comes out first, then 1, 2, 3 are still on the stack with 3 on top, so the next pop must return 3, not 2. A is possible: push 1, 2, 3 → pop 3, pop 2 → push 4, pop 4 → pop 1.
Multiple Choice · The Stack ADT
Question 4: top and size in an Array Stack
In an array-based stack of capacity cap, top is the index of the top item, and an empty stack has top = −1. What are the “full” condition and size()?
B: the last valid index is cap − 1, and since indices start at 0, the number of items is top + 1. A is the classic top/size mix-up: once top == cap, data[top] is already outside the array.
Short Answer · Implementation
Question 5: The Popped Cell
This pop() for an array-based stack of objects returns the right value but has a flaw. What is the flaw, and how do you fix it?
public E pop() { if (isEmpty()) throw new RuntimeException("empty"); return data[top--]; }
Show answer
The popped item's reference stays in cell data[top+1]. The stack no longer uses the object, but because the array still points to it, the garbage collector cannot reclaim it (a memory leak known as loitering).
public E pop() { if (isEmpty()) throw new RuntimeException("empty"); E x = data[top]; data[top--] = null; // let go return x; }
The operation is still O(1). A stack of a primitive type (int[]) doesn't have this problem.
Code Trace · Implementation
Question 6: Tracing a Bounded Array Stack
This code uses the ArrayStack class from the lecture. What are the data array and top after each line, and what does the program print?
Three cells, all null; an empty stack has top = −1.
top (−1) ≠ 2 → there is room. data[++top] = 10: top becomes 0 first, then the write happens.
top becomes 1; data[1] = 20.
x = data[1] = 20 is saved, the cell is set to null, and top drops to 0; 20 is printed (LIFO).
The freed cell 1 is reused: data[1] = 30.
top becomes 2; data[2] = 40. The array is now full.
top() returns 40 without removing it; size() = top + 1 = 3.
top == data.length − 1 (2 == 2) → overflow exception. A dynamic array would grow here.
ArrayStack<Integer> s = new ArrayStack<>(3);
s.push(10);
s.push(20);
System.out.println(s.pop());
s.push(30);
s.push(40);
System.out.println(s.top() + " " + s.size());
s.push(50);
Short Answer · Implementation
Question 7: The Cost of Doubling
An empty stack starts with capacity 1 and doubles its capacity whenever it is full (copying the old items into the new array). We push 9 times. How many copies and how many writes happen in total, what is the final capacity, and what does this say about the amortized cost of push?
Show answer
| push no. | 1 | 2 | 3 | 4 | 5 | 6–8 | 9 |
|---|---|---|---|---|---|---|---|
| growth | — | 1→2 | 2→4 | — | 4→8 | — | 8→16 |
| copies | 0 | 1 | 2 | 0 | 4 | 0 | 8 |
Copies: 1 + 2 + 4 + 8 = 15; writes: 9; total 24; final capacity 16.
24 < 3n = 27: over n pushes the copies total 1 + 2 + 4 + … < 2n, so the total is < 3n and the average per push is < 3 → amortized O(1). A single push that grows the array (the 9th) still takes O(n); the amortized bound is an average over a long sequence of operations.
Multiple Choice · Implementation
Question 8: Growing by a Fixed Amount
Instead of doubling, a dynamic-array stack adds 10 cells whenever it is full (10 → 20 → 30 → …). For n pushes onto an empty stack, what are the total cost and the average cost per push?
C: the copies total 10 + 20 + 30 + … + n ≈ n²/20 → O(n²); divided over n pushes, that is O(n) each. A holds only when capacity grows proportionally (e.g., ×2): then the copies form a geometric series and the total stays < 3n.
Multiple Choice · Implementation
Question 9: Array or Linked List?
Which statement about stack implementations is false?
A is false: a push that grows the array copies every item and takes O(n); only the amortized cost is O(1). D is true: Stack is Vector-based and synchronized, which makes it slower. In a linked list, the next reference in each item costs extra memory.
Short Answer · Applications
Question 10: Tracing Bracket Matching
What does the lecture's isBalanced method return for the input "[{()()}]{"? Show the stack after each character.
Show answer
| Character | Action | Stack (bottom→top) |
|---|---|---|
| [ { ( | 3 × push | [ { ( |
| ) | pop ( ✓ | [ { |
| ( | push | [ { ( |
| ) | pop ( ✓ | [ { |
| } | pop { ✓ | [ |
| ] | pop [ ✓ | empty |
| { | push | { |
| (end) | stack empty? | { left |
Result: false. Every closer matched, but an unclosed { is left at the end, so return stack.isEmpty() gives false. Time O(n); the stack holds at most O(n).
Multiple Choice · Applications
Question 11: The Empty-Stack Check
If the marked line is removed from isBalanced, which input throws an exception?
for (char c : s.toCharArray()) { if (c == '(' || c == '[' || c == '{') { stack.push(c); } else { if (stack.isEmpty()) return false; // removed char open = stack.pop(); if (!matches(open, c)) return false; } } return stack.isEmpty();
D: after "()" matches and the stack empties, the second ) pops an empty ArrayDeque → NoSuchElementException. A doesn't throw: ( is left at the end and the method returns false. In B, [ is on top when ) arrives, so they don't match → false; C is balanced → true.
Short Answer · Applications
Question 12: Next Greater Element
What does nextGreater(new int[]{6, 2, 9, 5, 5, 7, 1}) return? Show how the stack changes as the array is scanned from right to left.
for (int i = arr.length-1; i >= 0; i--) { while (!stack.isEmpty() && stack.peek() <= arr[i]) stack.pop(); result[i] = stack.isEmpty() ? -1 : stack.peek(); stack.push(arr[i]); }
Show answer
| i | arr[i] | popped | result[i] | stack (bottom→top) |
|---|---|---|---|---|
| 6 | 1 | — | −1 | 1 |
| 5 | 7 | 1 | −1 | 7 |
| 4 | 5 | — | 7 | 7 5 |
| 3 | 5 | 5 (≤ 5) | 7 | 7 5 |
| 2 | 9 | 5, 7 | −1 | 9 |
| 1 | 2 | — | 9 | 9 2 |
| 0 | 6 | 2 | 9 | 9 6 |
Result: [9, 9, −1, 7, 7, −1, −1]. The stack stays decreasing from bottom to top (a monotonic stack). Each item is pushed at most once and popped at most once → O(n) (brute force is O(n²)).
Short Answer · Applications
Question 13: A Stack with O(1) getMin
We run push(4), push(6), push(2), push(2), pop(), getMin(), pop(), getMin() in order. What do the two getMin() calls return, and what is left on the min stack at the end?
void push(int x) { s.push(x); if (min.isEmpty() || x <= min.peek()) min.push(x); } int pop() { int x = s.pop(); if (x == min.peek()) min.pop(); return x; } int getMin() { return min.peek(); }
Show answer
- After the pushes, s (bottom→top) is 4 6 2 2 and min is 4 2 2 (6 is skipped because 6 > 4; the second 2 goes in thanks to
<=). - pop() → 2; 2 == min.peek() → min: 4 2. getMin() → 2.
- pop() → 2; min: 4. getMin() → 4.
At the end the min stack holds 4. getMin only peeks → O(1).
With < instead, the second 2 would not go onto min, the first pop would remove min's only 2, and the first getMin() would wrongly return 4 (a 2 is still on the stack).
Code Trace · Hanoi and Stock Span
Question 14: Tracing Stock Span
What array does span({30, 20, 25, 10, 15, 40}) return?
First day: push index 0; span 1. The stack holds the indices of days not yet beaten.
20 ≥ prices[0] = 30? No → span = 1 − 0 = 1; push(1).
25 ≥ prices[1] = 20 → pop(1). Day 1 can no longer be anyone's boundary.
25 < 30 → stop. span = 2 − 0 = 2; push(2).
10 < 25 → span = 3 − 2 = 1; push(3).
15 ≥ prices[3] = 10 → pop(3).
15 < 25 → span = 4 − 2 = 2; push(4).
40 ≥ 15 → pop(4); 40 ≥ 25 → pop(2).
40 ≥ 30 → pop(0). The stack is empty: 40 beats every earlier price.
The stack is empty → span = i + 1 = 6; push(5).
Each index is pushed once and popped at most once → O(n).
int[] span(int[] prices) { int[] spans = new int[prices.length]; Deque<Integer> stack = new ArrayDeque<>(); stack.push(0); spans[0] = 1; for (int i = 1; i < prices.length; i++) { while (!stack.isEmpty() && prices[i] >= prices[stack.peek()]) stack.pop(); spans[i] = stack.isEmpty() ? i + 1 : i - stack.peek(); stack.push(i); } return spans; }
Multiple Choice · Expression Notation
Question 15: Right-Associative Power
^ (power) has the highest precedence and associates right to left. What is the postfix form of A ^ B ^ C * D?
C: right associativity means (A ^ (B ^ C)) * D. Option A reflects (A ^ B) ^ C, that is, left associativity. This is why, when ^ arrives, the algorithm does not pop an equal-precedence ^ from the top; it pops only operators of higher precedence.
Code Trace · Expression Notation
Question 16: Tracing Infix → Postfix
What string does infixToPostfix("A-B*(C+D)/E") return?
Precedence: + − → 1, * / → 2, ( → 0.
Operand → straight to the output.
The stack is empty → push(−).
Operand → output.
Top − (1) ≥ * (2)? No → push(*).
( is always pushed.
Operand → output.
( is on top (precedence 0) → nothing is popped; push(+).
Operand → output.
) → pop until (: + goes to the output.
( is discarded; parentheses never reach the output.
Top * (2) ≥ / (2) → * goes to the output (left associativity).
Top − (1) ≥ 2? No → push(/).
Operand → output.
End of input: / and then − go to the output. Result: A B C D + * E / −. O(n).
for (char c : expr.toCharArray()) { if (Character.isLetterOrDigit(c)) out.append(c); else if (c == '(') stack.push(c); else if (c == ')') { while (stack.peek() != '(') out.append(stack.pop()); stack.pop(); // discard '(' } else { // operator while (!stack.isEmpty() && prec(stack.peek()) >= prec(c)) out.append(stack.pop()); stack.push(c); } } while (!stack.isEmpty()) out.append(stack.pop());
Short Answer · Expression Notation
Question 17: Postfix Evaluation
Find the result of evaluatePostfix("623+*84/-"), writing down the operand stack after each token.
Show answer
| Read | Action | Stack (bottom→top) |
|---|---|---|
| 6, 2, 3 | 3 × push | 6 2 3 |
| + | right = 3, left = 2 → 2 + 3 = 5 | 6 5 |
| * | right = 5, left = 6 → 6 · 5 = 30 | 30 |
| 8, 4 | 2 × push | 30 8 4 |
| / | right = 4, left = 8 → 8 / 4 = 2 | 30 2 |
| − | right = 2, left = 30 → 30 − 2 = 28 | 28 |
Result: 28 (in infix, 6 * (2 + 3) − 8 / 4). One value is left on the stack at the end. No parentheses or precedence are needed, and each token is handled once → O(n).
Multiple Choice · Expression Notation
Question 18: Operand Order
What does the lecture's evaluatePostfix("82/3-") return?
if (Character.isDigit(c)) { stack.push(c - '0'); } else { int right = stack.pop(); int left = stack.pop(); stack.push(apply(left, c, right)); }
D: for /, right = 2 is popped first and then left = 8 → 8 / 2 = 4; for −, right = 3, left = 4 → 4 − 3 = 1. A (3) comes from mixing up the operand order: 2 / 8 = 0 (integer division), then 3 − 0 = 3. The first pop is the right operand, the second the left.
Multiple Choice · Summary
Question 19: Print Order
What does this code print?
Stack<Integer> s = new Stack<>(); Deque<Integer> d = new ArrayDeque<>(); for (int i = 1; i <= 3; i++) { s.push(i); d.push(i); } System.out.println(s + " " + d);
A: the legacy Stack (Vector-based) prints and iterates bottom to top, while ArrayDeque goes top to bottom (push adds at the front). The two stacks hold the same items, yet the output looks reversed; a for-each loop shows the same difference.
Multiple Choice · Expression Notation
Question 20: Infix → Prefix
What does the lecture's infixToPrefix (reverse, swap ( ↔ ), run postfix without popping on equal precedence, reverse the result) return for "A-B+C*D/E"?
B: left associativity means (A − B) + ((C * D) / E). A results from popping on equal precedence in step 3 as well; after the reversal the grouping runs right to left: A − (B + C * (D / E)). C is the postfix form of the expression. D is the output of step 3, with the final reversal forgotten.
Short Answer · Hanoi and Stock Span
Question 21: The Hanoi Task Stack
The lecture's stack-based hanoi method is called as hanoi(4); Task(n, from, via, to) means “move n disks from from to to using via”. After the first three pops, which tasks are on the stack (top to bottom)? What is the first move printed, and what is the most tasks the stack ever holds?
stack.push(new Task(n, 'A', 'B', 'C')); while (!stack.isEmpty()) { Task t = stack.pop(); if (t.n() == 1) System.out.println(t.from() + " → " + t.to()); else { // reverse order int m = t.n() - 1; stack.push(new Task(m, t.via(), t.from(), t.to())); stack.push(new Task(1, t.from(), t.via(), t.to())); stack.push(new Task(m, t.from(), t.to(), t.via())); } }
Show answer
| pop | popped | stack (top to bottom) |
|---|---|---|
| 1 | (4,A,B,C) | (3,A,C,B) (1,A,B,C) (3,B,A,C) |
| 2 | (3,A,C,B) | (2,A,B,C) (1,A,C,B) (2,C,A,B) (1,A,B,C) (3,B,A,C) |
| 3 | (2,A,B,C) | (1,A,C,B) (1,A,B,C) (1,B,A,C) (1,A,C,B) (2,C,A,B) (1,A,B,C) (3,B,A,C) |
The 4th pop, (1,A,C,B), gives the first move: A → B (disk 1). Because n is even, the smallest disk goes to B first; in hanoi(3) the first move was A → C.
Each expansion removes 1 task and adds 3 (net +2), and this happens n − 1 times in a row, so the stack holds at most 7 = 2n − 1 tasks. In all, 2⁴ − 1 = 15 moves are printed.
Multiple Choice · Applications
Question 22: Call Stack Depth
When the call stack is at its deepest, how many frames does it hold (counting main), and which frame is on top?
int fact(int n) { if (n <= 1) return 1; return n * fact(n - 1); } // in main: System.out.println(fact(4));
D: main → fact(4) → fact(3) → fact(2) → fact(1). The base case is n <= 1, so fact(0) is never called (B). C forgets main's frame. A reads the stack upside down: fact(4) sits just above main, and the most recent call is on top. Depth n + 1 → O(n) memory.
Multiple Choice · Applications
Question 23: StackOverflowError
The base case is written as n == 1. What happens when fact(0) is called?
int fact(int n) { if (n == 1) return 1; return n * fact(n - 1); } // in main: System.out.println(fact(0));
A: n = 0, −1, −2, … never reaches the base case; each call pushes a new frame, and when the thread's limited stack space fills up, the JVM throws StackOverflowError. D would be right for an infinite loop; in recursion every call uses memory, so the program crashes. B and C assume the base case catches 0; with n <= 1 it would return 1.
Short Answer · Applications
Question 24: Tracing Back / Forward
The browser follows the two-stack rules from the lecture: visit → push the current page onto back and clear forward; back → push the current page onto forward and pop back; forward → push the current page onto back and pop forward.
The current page is Home and both stacks are empty. We run visit(Mail), visit(Maps), visit(Video), back(), back(), forward(), visit(Blog), back() in order. Write both stacks and the current page after each operation. At the end, can forward() take us back to Video?
Show answer
| Operation | back (bottom→top) | current | forward (bottom→top) |
|---|---|---|---|
| visit(Mail) | Home | empty | |
| visit(Maps) | Home Mail | Maps | empty |
| visit(Video) | Home Mail Maps | Video | empty |
| back() | Home Mail | Maps | Video |
| back() | Home | Video Maps | |
| forward() | Home Mail | Maps | Video |
| visit(Blog) | Home Mail Maps | Blog | empty |
| back() | Home Mail | Maps | Blog |
At the end, forward() opens Blog. Video is out of reach: visit(Blog) started a new path and cleared the forward stack, which held Video. Each operation is O(1).