Stacks & Queues
Definition

Big O Complexity

When to Use

Pros and Cons

Implementation
Stack Implementation
// Using Array
public class ArrayStack<T> {
private Object[] data;
private int top;
private int capacity;
public ArrayStack(int capacity) {
this.capacity = capacity;
this.data = new Object[capacity];
this.top = -1;
}
public void push(T item) {
if (top == capacity - 1) {
resize();
}
data[++top] = item;
}
public T pop() {
if (isEmpty()) {
throw new EmptyStackException();
}
T item = (T) data[top];
data[top--] = null; // Help GC
return item;
}
public T peek() {
if (isEmpty()) {
throw new EmptyStackException();
}
return (T) data[top];
}
public boolean isEmpty() {
return top == -1;
}
public int size() {
return top + 1;
}
private void resize() {
capacity *= 2;
data = Arrays.copyOf(data, capacity);
}
}
// Using LinkedList
public class LinkedStack<T> {
private class Node {
T data;
Node next;
Node(T data) { this.data = data; }
}
private Node top;
private int size;
public void push(T item) {
Node newNode = new Node(item);
newNode.next = top;
top = newNode;
size++;
}
public T pop() {
if (isEmpty()) {
throw new EmptyStackException();
}
T item = top.data;
top = top.next;
size--;
return item;
}
public T peek() {
if (isEmpty()) {
throw new EmptyStackException();
}
return top.data;
}
public boolean isEmpty() {
return top == null;
}
public int size() {
return size;
}
}
// Java Built-in (prefer Deque over Stack class)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // Add to top
stack.pop(); // Remove from top
stack.peek(); // View top
Queue Implementation
// Using Circular Array
public class ArrayQueue<T> {
private Object[] data;
private int front, rear, size, capacity;
public ArrayQueue(int capacity) {
this.capacity = capacity;
this.data = new Object[capacity];
this.front = 0;
this.rear = -1;
this.size = 0;
}
public void enqueue(T item) {
if (size == capacity) {
resize();
}
rear = (rear + 1) % capacity;
data[rear] = item;
size++;
}
public T dequeue() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T item = (T) data[front];
data[front] = null;
front = (front + 1) % capacity;
size--;
return item;
}
public T peek() {
if (isEmpty()) {
throw new NoSuchElementException();
}
return (T) data[front];
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
private void resize() {
Object[] newData = new Object[capacity * 2];
for (int i = 0; i < size; i++) {
newData[i] = data[(front + i) % capacity];
}
data = newData;
front = 0;
rear = size - 1;
capacity *= 2;
}
}
// Using LinkedList
public class LinkedQueue<T> {
private class Node {
T data;
Node next;
Node(T data) { this.data = data; }
}
private Node front, rear;
private int size;
public void enqueue(T item) {
Node newNode = new Node(item);
if (rear == null) {
front = rear = newNode;
} else {
rear.next = newNode;
rear = newNode;
}
size++;
}
public T dequeue() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T item = front.data;
front = front.next;
if (front == null) {
rear = null;
}
size--;
return item;
}
public T peek() {
if (isEmpty()) {
throw new NoSuchElementException();
}
return front.data;
}
public boolean isEmpty() {
return front == null;
}
}
// Java Built-in
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // Add to back
queue.poll(); // Remove from front
queue.peek(); // View front
Deque Implementation
// Java Built-in ArrayDeque (recommended)
Deque<Integer> deque = new ArrayDeque<>();
// As Stack
deque.push(1); // addFirst
deque.pop(); // removeFirst
deque.peek(); // peekFirst
// As Queue
deque.offer(1); // addLast
deque.poll(); // removeFirst
deque.peek(); // peekFirst
// Double-ended operations
deque.addFirst(1);
deque.addLast(2);
deque.removeFirst();
deque.removeLast();
deque.peekFirst();
deque.peekLast();
Common Patterns & Problems
Valid Parentheses
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>();
Map<Character, Character> pairs = Map.of(
')', '(',
'}', '{',
']', '['
);
for (char c : s.toCharArray()) {
if (pairs.containsValue(c)) {
stack.push(c);
} else if (pairs.containsKey(c)) {
if (stack.isEmpty() || stack.pop() != pairs.get(c)) {
return false;
}
}
}
return stack.isEmpty();
}
Min Stack - O(1) getMin
class MinStack {
private Deque<Integer> stack;
private Deque<Integer> minStack;
public MinStack() {
stack = new ArrayDeque<>();
minStack = new ArrayDeque<>();
}
public void push(int val) {
stack.push(val);
if (minStack.isEmpty() || val <= minStack.peek()) {
minStack.push(val);
}
}
public void pop() {
if (stack.pop().equals(minStack.peek())) {
minStack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
Implement Queue using Stacks
class MyQueue {
private Deque<Integer> stackIn;
private Deque<Integer> stackOut;
public MyQueue() {
stackIn = new ArrayDeque<>();
stackOut = new ArrayDeque<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
shiftStacks();
return stackOut.pop();
}
public int peek() {
shiftStacks();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
private void shiftStacks() {
if (stackOut.isEmpty()) {
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
}
}
Implement Stack using Queues
class MyStack {
private Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.offer(x);
// Rotate to make new element at front
for (int i = 0; i < queue.size() - 1; i++) {
queue.offer(queue.poll());
}
}
public int pop() {
return queue.poll();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
}
Sliding Window Maximum (Monotonic Deque)
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0) return new int[0];
int[] result = new int[nums.length - k + 1];
Deque<Integer> deque = new ArrayDeque<>(); // Store indices
for (int i = 0; i < nums.length; i++) {
// Remove indices outside window
while (!deque.isEmpty() && deque.peekFirst() < i - k + 1) {
deque.pollFirst();
}
// Remove smaller elements (maintain decreasing order)
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
deque.offerLast(i);
// Add to result
if (i >= k - 1) {
result[i - k + 1] = nums[deque.peekFirst()];
}
}
return result;
}
Evaluate Reverse Polish Notation
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new ArrayDeque<>();
Set<String> operators = Set.of("+", "-", "*", "/");
for (String token : tokens) {
if (operators.contains(token)) {
int b = stack.pop();
int a = stack.pop();
switch (token) {
case "+": stack.push(a + b); break;
case "-": stack.push(a - b); break;
case "*": stack.push(a * b); break;
case "/": stack.push(a / b); break;
}
} else {
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
Daily Temperatures (Next Greater Element)
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] result = new int[n];
Deque<Integer> stack = new ArrayDeque<>(); // Store indices
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
int prevIndex = stack.pop();
result[prevIndex] = i - prevIndex;
}
stack.push(i);
}
return result;
}
Binary Tree Level Order Traversal (BFS with Queue)
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int levelSize = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
result.add(level);
}
return result;
}
Priority Queue (Bonus)
// Min Heap (default)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// Max Heap
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
// Custom comparator
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
// Operations - O(log n) for add/poll, O(1) for peek
minHeap.offer(5); // Add
minHeap.poll(); // Remove min
minHeap.peek(); // View min
// Common use: Top K elements, Merge K sorted lists
Tips & Tricks
