Stack Queue Questions Placement
Stack & Queue Questions for Placement 2026 (with Solutions)
Last Updated: March 2026
Overview
Stacks and Queues are fundamental linear data structures that form the backbone of many algorithms and system designs. A Stack follows LIFO (Last In, First Out) principle, while a Queue follows FIFO (First In, First Out). These structures are extensively tested in technical interviews at top tech companies.
Companies Focused on Stack & Queue
- Amazon: LRU Cache, Stock Span Problems
- Microsoft: Expression Evaluation, Parentheses Matching
- Google: Min Stack, Sliding Window Maximum
- Adobe: Implement Queue using Stacks
- Flipkart: Next Greater Element, LRU Implementation
- Uber: Ride-matching queue systems
Core Concepts
Stack (LIFO - Last In First Out)
Operations:
- push(x): Add element to top O(1)
- pop(): Remove top element O(1)
- peek()/top(): View top element O(1)
- isEmpty(): Check if empty O(1)
Visual Representation:
[5] <- Top (Last pushed)
[3]
[8]
[2] <- Bottom (First pushed)
Applications:
- Function call stack (recursion)
- Expression evaluation and conversion
- Backtracking algorithms
- Undo/Redo operations
- Browser history
Queue (FIFO - First In First Out)
Operations:
- enqueue(x): Add to rear O(1)
- dequeue(): Remove from front O(1)
- front(): View front element O(1)
- isEmpty(): Check if empty O(1)
Visual Representation:
Front -> [2] [8] [3] [5] <- Rear
(First) (Last)
Applications:
- CPU scheduling
- Printer spooling
- Breadth-First Search (BFS)
- Cache implementations (LRU)
- Message queues
Monotonic Stack/Queue
A monotonic stack/queue maintains elements in increasing or decreasing order. This is crucial for problems like:
- Next Greater Element
- Sliding Window Maximum
- Largest Rectangle in Histogram
20 Frequently Asked Coding Questions
Question 1: Implement Stack using Arrays
Problem: Implement a stack with push, pop, peek, and isEmpty operations.
class Stack:
def __init__(self, capacity=1000):
self.capacity = capacity
self.arr = [None] * capacity
self.top_idx = -1
def push(self, x):
if self.top_idx >= self.capacity - 1:
raise Exception("Stack Overflow")
self.top_idx += 1
self.arr[self.top_idx] = x
def pop(self):
if self.isEmpty():
raise Exception("Stack Underflow")
val = self.arr[self.top_idx]
self.top_idx -= 1
return val
def peek(self):
if self.isEmpty():
raise Exception("Stack is empty")
return self.arr[self.top_idx]
def isEmpty(self):
return self.top_idx == -1
def size(self):
return self.top_idx + 1
# Driver Code
stack = Stack()
stack.push(10)
stack.push(20)
stack.push(30)
print(stack.peek()) # Output: 30
print(stack.pop()) # Output: 30
print(stack.size()) # Output: 2
print(stack.isEmpty()) # Output: False
Time Complexity: All operations O(1)
Space Complexity: O(n) where n is capacity
Question 2: Implement Queue using Arrays (Circular Queue)
Problem: Implement a circular queue to efficiently use space.
class CircularQueue:
def __init__(self, capacity=1000):
self.capacity = capacity
self.arr = [None] * capacity
self.front = 0
self.rear = -1
self.size = 0
def enqueue(self, x):
if self.isFull():
raise Exception("Queue is full")
self.rear = (self.rear + 1) % self.capacity
self.arr[self.rear] = x
self.size += 1
def dequeue(self):
if self.isEmpty():
raise Exception("Queue is empty")
val = self.arr[self.front]
self.front = (self.front + 1) % self.capacity
self.size -= 1
return val
def front_elem(self):
if self.isEmpty():
raise Exception("Queue is empty")
return self.arr[self.front]
def isEmpty(self):
return self.size == 0
def isFull(self):
return self.size == self.capacity
# Driver Code
queue = CircularQueue(5)
queue.enqueue(10)
queue.enqueue(20)
queue.enqueue(30)
print(queue.front_elem()) # Output: 10
print(queue.dequeue()) # Output: 10
queue.enqueue(40)
queue.enqueue(50)
print(queue.size) # Output: 4
Time Complexity: All operations O(1)
Space Complexity: O(n)
Question 3: Implement Queue using Two Stacks
Problem: Implement a queue using only two stacks.
class QueueUsingStacks:
def __init__(self):
self.stack1 = [] # For enqueue
self.stack2 = [] # For dequeue
def enqueue(self, x):
self.stack1.append(x)
def dequeue(self):
if self.isEmpty():
raise Exception("Queue is empty")
# Transfer elements if stack2 is empty
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
def front(self):
if self.isEmpty():
raise Exception("Queue is empty")
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2[-1]
def isEmpty(self):
return not self.stack1 and not self.stack2
# Driver Code
queue = QueueUsingStacks()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
print(queue.front()) # Output: 1
print(queue.dequeue()) # Output: 1
print(queue.dequeue()) # Output: 2
queue.enqueue(4)
print(queue.dequeue()) # Output: 3
Time Complexity: Amortized O(1) for all operations
Space Complexity: O(n)
Question 4: Implement Stack using Two Queues
Problem: Implement a stack using only two queues.
from collections import deque
class StackUsingQueues:
def __init__(self):
self.queue1 = deque()
self.queue2 = deque()
def push(self, x):
# Add to queue2
self.queue2.append(x)
# Move all elements from queue1 to queue2
while self.queue1:
self.queue2.append(self.queue1.popleft())
# Swap queues
self.queue1, self.queue2 = self.queue2, self.queue1
def pop(self):
if self.isEmpty():
raise Exception("Stack is empty")
return self.queue1.popleft()
def top(self):
if self.isEmpty():
raise Exception("Stack is empty")
return self.queue1[0]
def isEmpty(self):
return not self.queue1
# Driver Code
stack = StackUsingQueues()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.top()) # Output: 3
print(stack.pop()) # Output: 3
print(stack.pop()) # Output: 2
Time Complexity: Push O(n), Pop O(1)
Space Complexity: O(n)
Question 5: Valid Parentheses
Problem: Given a string containing brackets, determine if it's valid.
class Solution:
def isValid(self, s: str) -> bool:
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping: # Closing bracket
if not stack or stack.pop() != mapping[char]:
return False
else: # Opening bracket
stack.append(char)
return not stack
# Driver Code
sol = Solution()
print(sol.isValid("()")) # Output: True
print(sol.isValid("()[]{}")) # Output: True
print(sol.isValid("(]")) # Output: False
print(sol.isValid("([)]")) # Output: False
print(sol.isValid("{[]}")) # Output: True
Time Complexity: O(n)
Space Complexity: O(n)
Question 6: Next Greater Element I
Problem: For each element in nums1, find the next greater element in nums2.
class Solution:
def nextGreaterElement(self, nums1, nums2):
# Monotonic decreasing stack
stack = []
next_greater = {}
for num in nums2:
while stack and stack[-1] < num:
next_greater[stack.pop()] = num
stack.append(num)
# Remaining elements have no greater element
while stack:
next_greater[stack.pop()] = -1
return [next_greater[num] for num in nums1]
# Driver Code
nums1 = [4, 1, 2]
nums2 = [1, 3, 4, 2]
sol = Solution()
print(sol.nextGreaterElement(nums1, nums2)) # Output: [-1, 3, -1]
Time Complexity: O(n)
Space Complexity: O(n)
Question 7: Next Greater Element II (Circular Array)
Problem: Find next greater element for each element in circular array.
class Solution:
def nextGreaterElements(self, nums):
n = len(nums)
result = [-1] * n
stack = [] # Store indices
# Traverse twice for circular effect
for i in range(2 * n - 1, -1, -1):
actual_idx = i % n
while stack and nums[stack[-1]] <= nums[actual_idx]:
stack.pop()
if stack:
result[actual_idx] = nums[stack[-1]]
stack.append(actual_idx)
return result
# Driver Code
nums = [1, 2, 1]
sol = Solution()
print(sol.nextGreaterElements(nums)) # Output: [2, -1, 2]
Time Complexity: O(n)
Space Complexity: O(n)
Question 8: Min Stack
Problem: Design a stack that supports push, pop, top, and getMin in constant time.
class MinStack:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, val: int) -> None:
self.stack.append(val)
# Push to min_stack if empty or val <= current min
if not self.min_stack or val <= self.min_stack[-1]:
self.min_stack.append(val)
def pop(self) -> None:
val = self.stack.pop()
if val == self.min_stack[-1]:
self.min_stack.pop()
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_stack[-1]
# Driver Code
minStack = MinStack()
minStack.push(-2)
minStack.push(0)
minStack.push(-3)
print(minStack.getMin()) # Output: -3
minStack.pop()
print(minStack.top()) # Output: 0
print(minStack.getMin()) # Output: -2
Time Complexity: All operations O(1)
Space Complexity: O(n)
Question 9: Sliding Window Maximum
Problem: Find maximum in every window of size k.
from collections import deque
class Solution:
def maxSlidingWindow(self, nums, k):
result = []
dq = deque() # Store indices, maintain decreasing order
for i, num in enumerate(nums):
# Remove elements outside window
if dq and dq[0] < i - k + 1:
dq.popleft()
# Remove smaller elements from back
while dq and nums[dq[-1]] < num:
dq.pop()
dq.append(i)
# Add to result when window is full
if i >= k - 1:
result.append(nums[dq[0]])
return result
# Driver Code
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
sol = Solution()
print(sol.maxSlidingWindow(nums, k)) # Output: [3, 3, 5, 5, 6, 7]
Time Complexity: O(n)
Space Complexity: O(k)
Question 10: Largest Rectangle in Histogram
Problem: Find the largest rectangle area in a histogram.
class Solution:
def largestRectangleArea(self, heights):
stack = [] # Store indices
max_area = 0
n = len(heights)
for i in range(n):
while stack and heights[stack[-1]] > heights[i]:
height = heights[stack.pop()]
width = i if not stack else i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
# Process remaining elements
while stack:
height = heights[stack.pop()]
width = n if not stack else n - stack[-1] - 1
max_area = max(max_area, height * width)
return max_area
# Driver Code
heights = [2, 1, 5, 6, 2, 3]
sol = Solution()
print(sol.largestRectangleArea(heights)) # Output: 10
Time Complexity: O(n)
Space Complexity: O(n)
Question 11: Stock Span Problem
Problem: Calculate stock span for each day (consecutive days with price <= current).
class Solution:
def calculateSpan(self, price, n):
span = [0] * n
stack = [] # Store indices
for i in range(n):
# Pop elements with price <= current
while stack and price[stack[-1]] <= price[i]:
stack.pop()
if not stack:
span[i] = i + 1
else:
span[i] = i - stack[-1]
stack.append(i)
return span
# Driver Code
price = [100, 80, 60, 70, 60, 75, 85]
n = len(price)
sol = Solution()
print(sol.calculateSpan(price, n)) # Output: [1, 1, 1, 2, 1, 4, 6]
Time Complexity: O(n)
Space Complexity: O(n)
Question 12: LRU Cache Implementation
Problem: Design and implement an LRU (Least Recently Used) cache.
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key: int) -> int:
if key not in self.cache:
return -1
# Move to end (most recently used)
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
# Remove first item (least recently used)
self.cache.popitem(last=False)
# Without OrderedDict (using Doubly Linked List + HashMap)
class Node:
def __init__(self, key=0, val=0):
self.key = key
self.val = val
self.prev = None
self.next = None
class LRUCacheOptimized:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
def _remove(self, node):
prev, nxt = node.prev, node.next
prev.next, nxt.prev = nxt, prev
def _add_to_front(self, node):
node.next = self.head.next
node.prev = self.head
self.head.next.prev = node
self.head.next = node
def get(self, key: int) -> int:
if key not in self.cache:
return -1
node = self.cache[key]
self._remove(node)
self._add_to_front(node)
return node.val
def put(self, key: int, value: int) -> None:
if key in self.cache:
self._remove(self.cache[key])
node = Node(key, value)
self.cache[key] = node
self._add_to_front(node)
if len(self.cache) > self.capacity:
lru = self.tail.prev
self._remove(lru)
del self.cache[lru.key]
# Driver Code
cache = LRUCacheOptimized(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1)) # Output: 1
cache.put(3, 3) # Evicts key 2
print(cache.get(2)) # Output: -1
cache.put(4, 4) # Evicts key 1
print(cache.get(1)) # Output: -1
print(cache.get(3)) # Output: 3
print(cache.get(4)) # Output: 4
Time Complexity: Get and Put O(1)
Space Complexity: O(capacity)
Question 13: Evaluate Reverse Polish Notation
Problem: Evaluate the value of an arithmetic expression in Reverse Polish Notation.
class Solution:
def evalRPN(self, tokens):
stack = []
for token in tokens:
if token in "+-*/":
b = stack.pop()
a = stack.pop()
if token == '+':
stack.append(a + b)
elif token == '-':
stack.append(a - b)
elif token == '*':
stack.append(a * b)
else: # Division
stack.append(int(a / b))
else:
stack.append(int(token))
return stack[0]
# Driver Code
tokens = ["2", "1", "+", "3", "*"]
sol = Solution()
print(sol.evalRPN(tokens)) # Output: 9
tokens2 = ["4", "13", "5", "/", "+"]
print(sol.evalRPN(tokens2)) # Output: 6
Time Complexity: O(n)
Space Complexity: O(n)
Question 14: Daily Temperatures
Problem: Find days until a warmer temperature for each day.
class Solution:
def dailyTemperatures(self, temperatures):
n = len(temperatures)
result = [0] * n
stack = [] # Store indices
for i in range(n):
while stack and temperatures[stack[-1]] < temperatures[i]:
prev_idx = stack.pop()
result[prev_idx] = i - prev_idx
stack.append(i)
return result
# Driver Code
temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
sol = Solution()
print(sol.dailyTemperatures(temperatures)) # Output: [1, 1, 4, 2, 1, 1, 0, 0]
Time Complexity: O(n)
Space Complexity: O(n)
Question 15: Online Stock Span
Problem: Design an algorithm that collects daily price quotes and returns the span.
class StockSpanner:
def __init__(self):
self.stack = [] # (price, span)
def next(self, price: int) -> int:
span = 1
while self.stack and self.stack[-1][0] <= price:
span += self.stack.pop()[1]
self.stack.append((price, span))
return span
# Driver Code
stockSpanner = StockSpanner()
print(stockSpanner.next(100)) # Output: 1
print(stockSpanner.next(80)) # Output: 1
print(stockSpanner.next(60)) # Output: 1
print(stockSpanner.next(70)) # Output: 2
print(stockSpanner.next(60)) # Output: 1
print(stockSpanner.next(75)) # Output: 4
print(stockSpanner.next(85)) # Output: 6
Time Complexity: Amortized O(1) per query
Space Complexity: O(n)
Question 16: Simplify Path
Problem: Convert Unix-style absolute path to simplified canonical path.
class Solution:
def simplifyPath(self, path: str) -> str:
stack = []
components = path.split('/')
for comp in components:
if comp == '' or comp == '.':
continue
elif comp == '..':
if stack:
stack.pop()
else:
stack.append(comp)
return '/' + '/'.join(stack)
# Driver Code
sol = Solution()
print(sol.simplifyPath("/home/")) # Output: "/home"
print(sol.simplifyPath("/../")) # Output: "/"
print(sol.simplifyPath("/home//foo/")) # Output: "/home/foo"
print(sol.simplifyPath("/a/./b/../../c/")) # Output: "/c"
Time Complexity: O(n)
Space Complexity: O(n)
Question 17: Implement Stack with Increment Operation
Problem: Design a stack with push, pop, and increment operations.
class CustomStack:
def __init__(self, maxSize: int):
self.stack = []
self.maxSize = maxSize
self.inc = [] # Increment tracking
def push(self, x: int) -> None:
if len(self.stack) < self.maxSize:
self.stack.append(x)
self.inc.append(0)
def pop(self) -> int:
if not self.stack:
return -1
# Propagate increment to below element
if len(self.inc) > 1:
self.inc[-2] += self.inc[-1]
return self.stack.pop() + self.inc.pop()
def increment(self, k: int, val: int) -> None:
if self.inc:
idx = min(k, len(self.inc)) - 1
self.inc[idx] += val
# Driver Code
customStack = CustomStack(3)
customStack.push(1)
customStack.push(2)
print(customStack.pop()) # Output: 2
customStack.push(2)
customStack.push(3)
customStack.push(4) # Stack is full
customStack.increment(5, 100)
customStack.increment(2, 100)
print(customStack.pop()) # Output: 103
print(customStack.pop()) # Output: 202
print(customStack.pop()) # Output: 201
Time Complexity: Push O(1), Pop O(1), Increment O(1)
Space Complexity: O(n)
Question 18: Number of Recent Calls
Problem: Count recent calls within 3000 milliseconds window.
from collections import deque
class RecentCounter:
def __init__(self):
self.queue = deque()
def ping(self, t: int) -> int:
self.queue.append(t)
# Remove pings older than 3000ms
while self.queue[0] < t - 3000:
self.queue.popleft()
return len(self.queue)
# Driver Code
recentCounter = RecentCounter()
print(recentCounter.ping(1)) # Output: 1
print(recentCounter.ping(100)) # Output: 2
print(recentCounter.ping(3001)) # Output: 3
print(recentCounter.ping(3002)) # Output: 3
Time Complexity: Amortized O(1) per ping
Space Complexity: O(3000) = O(1)
Question 19: Maximum Frequency Stack
Problem: Implement a stack that pops the most frequent element.
from collections import defaultdict
class FreqStack:
def __init__(self):
self.freq = defaultdict(int) # element -> frequency
self.group = defaultdict(list) # frequency -> list of elements
self.max_freq = 0
def push(self, val: int) -> None:
self.freq[val] += 1
f = self.freq[val]
self.max_freq = max(self.max_freq, f)
self.group[f].append(val)
def pop(self) -> int:
val = self.group[self.max_freq].pop()
self.freq[val] -= 1
if not self.group[self.max_freq]:
self.max_freq -= 1
return val
# Driver Code
freqStack = FreqStack()
freqStack.push(5)
freqStack.push(7)
freqStack.push(5)
freqStack.push(7)
freqStack.push(4)
freqStack.push(5)
print(freqStack.pop()) # Output: 5
print(freqStack.pop()) # Output: 7
print(freqStack.pop()) # Output: 5
print(freqStack.pop()) # Output: 4
Time Complexity: Push O(1), Pop O(1)
Space Complexity: O(n)
Question 20: Trapping Rain Water
Problem: Calculate how much water can be trapped after raining.
class Solution:
def trap(self, height):
if not height:
return 0
n = len(height)
left, right = 0, n - 1
left_max, right_max = 0, 0
water = 0
while left < right:
if height[left] < height[right]:
if height[left] >= left_max:
left_max = height[left]
else:
water += left_max - height[left]
left += 1
else:
if height[right] >= right_max:
right_max = height[right]
else:
water += right_max - height[right]
right -= 1
return water
# Alternative: Stack-based approach
def trap_stack(height):
stack = []
water = 0
for i, h in enumerate(height):
while stack and height[stack[-1]] < h:
top = stack.pop()
if not stack:
break
distance = i - stack[-1] - 1
bounded_height = min(height[stack[-1]], h) - height[top]
water += distance * bounded_height
stack.append(i)
return water
# Driver Code
height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
sol = Solution()
print(sol.trap(height)) # Output: 6
Time Complexity: O(n)
Space Complexity: O(1) for two-pointer, O(n) for stack
MCQ Questions
Question 1
What is the time complexity of push operation in a stack?
- A) O(n)
- B) O(log n)
- C) O(1)
- D) O(n²)
Question 2
Which data structure is used to implement recursion?
- A) Queue
- B) Stack
- C) Array
- D) Linked List
Question 3
What principle does a Queue follow?
- A) LIFO
- B) FIFO
- C) LILO
- D) FILO
Question 4
In a monotonic decreasing stack, elements are stored in:
- A) Increasing order from bottom to top
- B) Decreasing order from bottom to top
- C) Random order
- D) Sorted order
Question 5
Which problem can be efficiently solved using a monotonic queue?
- A) Sorting
- B) Sliding Window Maximum
- C) Binary Search
- D) Matrix Multiplication
Interview Tips for Stack & Queue
-
Understand the fundamentals: Know LIFO vs FIFO thoroughly
-
Practice these patterns:
- Monotonic stack for next greater/smaller element
- Two stacks for implementing queues
- Stack for expression evaluation
- Queue for sliding window problems
-
Common interview scenarios:
- Implementing data structures from scratch
- Solving problems with space constraints
- Time complexity analysis
-
Edge cases to handle:
- Empty stack/queue operations
- Overflow conditions
- Single element
- Maximum capacity
-
System Design applications:
- Browser history (stack)
- Print spooling (queue)
- Undo/Redo operations (stack)
- Rate limiting (queue)
Frequently Asked Questions
Q1: When to use Stack vs Queue?
A: Use Stack for LIFO operations (backtracking, expression evaluation, undo). Use Queue for FIFO operations (BFS, scheduling, caching, level-order traversal).
Q2: How do I implement a Queue using Stacks efficiently?
A: Use two stacks. Push to stack1. When popping, if stack2 is empty, transfer all elements from stack1 to stack2. This gives amortized O(1) time complexity.
Q3: What is a Monotonic Stack?
A: A stack that maintains elements in either strictly increasing or decreasing order. Used for Next Greater Element, Largest Rectangle in Histogram, etc.
Q4: How does LRU Cache work?
A: LRU Cache uses a combination of HashMap (for O(1) access) and Doubly Linked List (for O(1) removal/addition). Most recently used items move to front, least recently used at back.
Q5: What is the advantage of Circular Queue?
A: Circular Queue efficiently utilizes space by reusing empty locations created after dequeue operations, preventing "false overflow" in regular queues.
Master these stack and queue problems to excel in technical interviews. Focus on understanding patterns rather than memorizing solutions.
Explore this topic cluster
More resources in Uncategorized
Use the category hub to browse similar questions, exam patterns, salary guides, and preparation resources related to this topic.