Stack Interview Questions
Stacks are a fundamental data structure frequently discussed in coding and technical interviews. Most stack questions test your understanding of the LIFO principle and your ability to recognize when the most recently added element needs to be processed first.
Common interview problems include implementing stacks, checking balanced parentheses, reversing data, evaluating expressions, tracking minimum values, and solving next greater element problems with a monotonic stack.
1. What Is a Stack?
A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. The element added most recently is the first element removed.
Push 10
Push 20
Push 30
Top
↓
30
20
10
Pop → 30
A stack is commonly used when the most recent operation, item, or state needs to be processed before earlier ones.
2. What Does LIFO Mean?
LIFO means Last In, First Out. The last element inserted into the stack is the first element removed.
Push A
Push B
Push C
Stack:
C ← removed first
B
A
Pop → C
A simple real-world analogy is a stack of plates. The most recently placed plate is normally the first plate removed.
3. What Are the Main Stack Operations?
The standard stack operations are:
- Push: adds an element to the top.
- Pop: removes and returns the top element.
- Peek: returns the top element without removing it.
- isEmpty: checks whether the stack contains elements.
- Size: returns the number of elements.
| Operation | Typical Time |
|---|---|
| Push | O(1) |
| Pop | O(1) |
| Peek | O(1) |
| isEmpty | O(1) |
4. How Do You Implement a Stack Using an Array?
An array can represent a stack by treating its final element as the top of the stack.
JavaScript's push() and pop() methods provide convenient
stack operations.
class Stack {
constructor() {
this.items = [];
}
push(value) {
this.items.push(value);
}
pop() {
return this.items.pop();
}
peek() {
return this.items[
this.items.length - 1
];
}
isEmpty() {
return this.items.length === 0;
}
size() {
return this.items.length;
}
}
const stack = new Stack();
stack.push(10);
stack.push(20);
stack.push(30);
console.log(stack.peek());
// 30
console.log(stack.pop());
// 30
5. Can a Stack Be Implemented Using a Linked List?
Yes. The head of a singly linked list can represent the top of the stack. Pushing and popping at the head can both be performed in O(1) time.
Top
↓
30 → 20 → 10 → null
Pop:
Top
↓
20 → 10 → null
A linked-list implementation can grow dynamically without requiring an array resize, although each node requires additional reference storage.
6. What Is Stack Overflow?
Stack overflow can refer to exceeding the available capacity of a fixed-size stack. In programming languages, the term is also commonly associated with exhausting the call stack through excessive or uncontrolled recursion.
function infiniteRecursion() {
infiniteRecursion();
}
infiniteRecursion();
Each recursive call creates another stack frame. If recursion continues without a terminating condition, the call stack can eventually be exhausted.
7. What Is Stack Underflow?
Stack underflow occurs when an application attempts to remove or inspect an element from an empty stack.
const stack = [];
stack.pop();
// No element exists to remove.
A robust stack implementation should define how empty-stack operations are handled,
such as returning null, undefined, or throwing an error.
8. What Is the Difference Between Stack and Queue?
A stack follows LIFO, while a queue follows FIFO.
| Feature | Stack | Queue |
|---|---|---|
| Principle | LIFO | FIFO |
| Insert | Top | Rear |
| Remove | Top | Front |
| Common use | Undo, recursion, DFS | Scheduling, BFS |
9. How Do You Check for Balanced Parentheses?
A stack is ideal for checking balanced brackets because the most recently opened bracket must be the first one closed.
function isBalanced(expression) {
const stack = [];
const pairs = {
")": "(",
"]": "[",
"}": "{"
};
for (const character of expression) {
if (
character === "(" ||
character === "[" ||
character === "{"
) {
stack.push(character);
} else if (
character === ")" ||
character === "]" ||
character === "}"
) {
if (
stack.length === 0 ||
stack.pop() !== pairs[character]
) {
return false;
}
}
}
return stack.length === 0;
}
console.log(isBalanced("{[()]}"));
// true
console.log(isBalanced("{[(])}"));
// false
The algorithm takes O(n) time and O(n) space in the worst case.
10. Why Is a Stack Useful for Parentheses Matching?
Consider nested brackets:
{ [ ( ) ] }
The closing parenthesis must match the most recently opened parenthesis. That is exactly the behavior provided by LIFO.
11. How Do You Reverse a String Using a Stack?
Push each character onto a stack and then pop the characters one by one. Because the last character pushed is removed first, the resulting string is reversed.
function reverseString(text) {
const stack = [];
for (const character of text) {
stack.push(character);
}
let result = "";
while (stack.length > 0) {
result += stack.pop();
}
return result;
}
console.log(reverseString("hello"));
// olleh
12. How Do You Evaluate a Postfix Expression Using a Stack?
In postfix notation, operators appear after their operands. A stack can store operands until an operator is encountered.
Expression:
2 3 + 4 *
Step 1:
Push 2
Step 2:
Push 3
Step 3:
+ → 2 + 3 = 5
Step 4:
Push 4
Step 5:
* → 5 * 4 = 20
function evaluatePostfix(tokens) {
const stack = [];
for (const token of tokens) {
if (!isNaN(token)) {
stack.push(Number(token));
continue;
}
const right = stack.pop();
const left = stack.pop();
if (token === "+") {
stack.push(left + right);
} else if (token === "-") {
stack.push(left - right);
} else if (token === "*") {
stack.push(left * right);
} else if (token === "/") {
stack.push(left / right);
}
}
return stack.pop();
}
console.log(
evaluatePostfix(["2", "3", "+", "4", "*"])
);
// 20
13. What Are Infix, Prefix, and Postfix Expressions?
These terms describe where operators appear relative to operands.
| Notation | Example | Operator Position |
|---|---|---|
| Infix | A + B | Between operands |
| Prefix | + A B | Before operands |
| Postfix | A B + | After operands |
Stacks are frequently used to convert between these expression formats and to evaluate postfix or prefix expressions.
14. How Do You Implement Two Stacks in One Array?
Two stacks can share a single array by growing from opposite ends. One stack starts from the beginning and the other starts from the end.
Stack 1 → → → ← ← ← Stack 2
[10][20][ ][ ][ ][30][40][50]
↑ ↑
top1 top2
The array has available space as long as the two top positions have not crossed.
15. How Do You Implement a Stack Using Two Queues?
A stack can be simulated with two queues by rearranging elements so that the most recently inserted item becomes available for removal first.
One common approach makes push expensive: insert the new element into one
queue and move all existing elements behind it.
Push 10:
[10]
Push 20:
[20, 10]
Push 30:
[30, 20, 10]
Pop:
30
This approach gives O(n) push and O(1) pop.
16. How Do You Implement a Queue Using Two Stacks?
Two stacks can simulate FIFO behavior. One stack receives new elements and the other provides elements for removal.
Input Stack:
[30, 20, 10]
Move to Output Stack:
[10, 20, 30]
Pop → 10
With the standard two-stack implementation, elements are transferred only when the output stack is empty, giving amortized O(1) queue operations.
17. What Is the Call Stack?
The call stack is a runtime stack used to keep track of active function calls. Each function call creates a stack frame containing information needed while that function executes.
function first() {
second();
}
function second() {
third();
}
function third() {
console.log("Hello");
}
first();
Call stack:
third()
second()
first()
When a function returns, its frame is removed from the call stack.
18. Why Is Recursion Related to Stacks?
Recursive function calls are stored on the call stack. The most recent function call must finish before the previous call can continue, which naturally follows LIFO behavior.
function countDown(n) {
if (n === 0) {
return;
}
console.log(n);
countDown(n - 1);
}
countDown(3);
Call sequence:
countDown(3)
countDown(2)
countDown(1)
countDown(0)
19. How Can DFS Be Implemented Using a Stack?
Depth-First Search can be implemented iteratively by placing nodes onto a stack. The most recently discovered node is processed first.
function dfs(graph, start) {
const stack = [start];
const visited = new Set();
while (stack.length > 0) {
const node = stack.pop();
if (visited.has(node)) {
continue;
}
visited.add(node);
console.log(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
stack.push(neighbor);
}
}
}
}
A stack-based DFS uses O(V) auxiliary space in the worst case, where V is the number of vertices.
20. What Is a Monotonic Stack?
A monotonic stack is a stack maintained so that its elements remain in increasing or decreasing order according to a chosen comparison.
Monotonic stacks are useful for problems involving the next greater element, next smaller element, previous greater element, stock spans, and temperature ranges.
21. What Is the Next Greater Element Problem?
For each element in an array, the goal is to find the first element to its right that is greater than it.
Input:
[4, 5, 2, 10]
Output:
[5, 10, 10, -1]
A decreasing monotonic stack can solve this problem in O(n) time because each element is pushed and popped at most once.
function nextGreaterElements(values) {
const result = new Array(values.length).fill(-1);
const stack = [];
for (let i = 0; i < values.length; i++) {
while (
stack.length > 0 &&
values[i] > values[stack[stack.length - 1]]
) {
const index = stack.pop();
result[index] = values[i];
}
stack.push(i);
}
return result;
}
console.log(
nextGreaterElements([4, 5, 2, 10])
);
// [5, 10, 10, -1]
22. Why Is the Monotonic Stack Algorithm O(n)?
Although the code contains a nested loop, every array element is pushed onto the stack at most once and removed from the stack at most once.
Therefore, the total number of stack operations is proportional to n, giving an overall time complexity of O(n).
23. How Do You Find the Minimum Element in O(1) Time?
A special stack can maintain the minimum value seen so far. One approach stores a pair containing the actual value and the minimum value at that position.
class MinStack {
constructor() {
this.stack = [];
}
push(value) {
const minimum =
this.stack.length === 0
? value
: Math.min(
value,
this.getMin()
);
this.stack.push({
value,
minimum
});
}
pop() {
return this.stack.pop()?.value;
}
getMin() {
if (this.stack.length === 0) {
return null;
}
return this.stack[
this.stack.length - 1
].minimum;
}
}
const stack = new MinStack();
stack.push(5);
stack.push(3);
stack.push(7);
stack.push(2);
console.log(stack.getMin());
// 2
stack.pop();
console.log(stack.getMin());
// 3
Both push and minimum lookup can be performed in O(1) time.
24. How Do You Sort a Stack?
A stack can be sorted using another temporary stack. Elements are moved between the two stacks while maintaining the desired ordering.
The exact implementation depends on whether the smallest or largest element should remain at the top, but the important interview concept is using another stack to preserve LIFO access.
25. How Do You Remove Adjacent Duplicates Using a Stack?
Push characters onto a stack. If the next character matches the current stack top, remove the top instead of adding the duplicate.
function removeAdjacentDuplicates(text) {
const stack = [];
for (const character of text) {
if (
stack.length > 0 &&
stack[stack.length - 1] === character
) {
stack.pop();
} else {
stack.push(character);
}
}
return stack.join("");
}
console.log(
removeAdjacentDuplicates("abbaca")
);
// "ca"
Each character is pushed and popped at most once, so the algorithm runs in O(n) time.
26. What Is the Difference Between a Stack and a Heap?
In data structures, a stack and a heap are fundamentally different concepts. A stack follows LIFO access, while a heap is a tree-based structure used for priority ordering.
In programming-language runtime discussions, the terms stack memory and heap memory refer to different memory-management regions. This is separate from the heap data structure used to implement priority queues.
27. What Are Common Applications of Stacks?
- Function call management.
- Recursion and backtracking.
- Undo and redo operations.
- Browser navigation history.
- Expression evaluation.
- Expression conversion.
- Parentheses and syntax matching.
- Depth-First Search.
- Backtracking algorithms.
- Monotonic stack problems.
28. What Is the Time Complexity of Stack Operations?
| Operation | Time | Typical Extra Space |
|---|---|---|
| Push | O(1) amortized with dynamic array | O(1) per element |
| Pop | O(1) | O(1) |
| Peek | O(1) | O(1) |
| Search | O(n) | O(1) |
29. What Are the Most Important Stack Interview Patterns?
Many stack interview problems can be grouped into a small number of reusable patterns.
| Pattern | Common Problems |
|---|---|
| Basic LIFO | Push, pop, peek, reverse |
| Matching | Balanced parentheses, syntax validation |
| Expression stack | Postfix evaluation, infix conversion |
| Monotonic stack | Next greater, next smaller, stock span |
| Auxiliary stack | Min Stack, sorting a stack |
| Simulation | Queue using stacks, stack using queues |
30. How Should You Approach a Stack Interview Problem?
When a problem involves recently encountered items, nested structures, matching pairs, or reversing the processing order, consider whether a stack fits the problem.
- Identify whether the problem naturally follows LIFO behavior.
- Determine what information needs to remain on the stack.
- Define exactly when an element should be pushed.
- Define the condition for popping elements.
- Check what the stack top represents at every step.
- Test empty-stack and single-element cases.
- Analyze whether every element is pushed and popped once.
- State the time and auxiliary-space complexity.
Common Stack Interview Mistakes
Ignoring Empty Stack Cases
Always check whether the stack contains an element before calling pop or accessing the top element.
Confusing Peek with Pop
Peek reads the top element without removing it. Pop removes the top element.
Using a Nested Loop Without Analyzing It
Monotonic stack algorithms often contain a while loop inside a for loop but still run in O(n) because each element can be pushed and popped only a limited number of times.
Losing the Stack Invariant
For specialized stacks such as monotonic stacks or Min Stack, clearly define what property the stack must maintain after every operation.
Stack Interview Revision Sheet
Stack principle → LIFO
Push → O(1)
Pop → O(1)
Peek → O(1)
Search → O(n)
Balanced brackets → Stack
Expression evaluation → Stack
DFS → Stack
Recursion → Call stack
Undo/Redo → Stack
Next greater element → Monotonic stack
Min Stack → Auxiliary minimum tracking
Common patterns:
- Matching
- Reversal
- Monotonic stack
- Auxiliary stack
- Expression processing
- Simulation
Key Takeaways
- A stack follows the Last In, First Out principle.
- Push, pop, and peek are normally O(1) operations.
- Stacks can be implemented using arrays or linked lists.
- Balanced parentheses are a classic stack problem.
- Recursion uses the runtime call stack.
- DFS can be implemented iteratively with a stack.
- Monotonic stacks solve many next-greater and next-smaller problems efficiently.
- An auxiliary stack can provide additional information such as the minimum value.
- Always define the invariant maintained by a specialized stack.
- For interviews, recognize the LIFO pattern before choosing a stack.