Queue Fundamentals
Queue Fundamentals
A queue is a First In First Out (FIFO) data structure. Think of a line at a grocery store - first person in line is first to be served.
Core Operations
| Operation | Description | Time |
|---|---|---|
| enqueue/add | Add element to rear | O(1) |
| dequeue/remove | Remove element from front | O(1) |
| peek/front | View front element | O(1) |
| isEmpty | Check if empty | O(1) |
Visual Example
enqueue(1) → [1]
enqueue(2) → [1, 2]
enqueue(3) → [1, 2, 3]
peek() → returns 1
dequeue() → returns 1, queue becomes [2, 3]
Java Queue Implementation
// Using Queue interface
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // or queue.add(1)
queue.offer(2);
int front = queue.peek(); // 1
int val = queue.poll(); // 1
// Using ArrayDeque (preferred)
Deque<Integer> deque = new ArrayDeque<>();
deque.offer(1); // or deque.addLast(1)
deque.offer(2);
int front = deque.peek(); // 1
int val = deque.poll(); // 1
Queue Variants
- Deque (Double-Ended Queue) - add/remove from both ends
- Priority Queue - elements served by priority
- Circular Queue - wraps around array
When to Use Queue
- BFS traversal - level-order traversal
- Scheduling - CPU, disk scheduling
- Buffering - print queue, IO buffer
- Sliding window - max in window
- Process management - OS process queues
Queue Applications
Queue Applications
1. BFS Traversal (Level Order)
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 size = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; 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;
}
2. Sliding Window Maximum (LeetCode 239)
public int[] maxSlidingWindow(int[] nums, int k) {
Deque<Integer> deque = new ArrayDeque<>();
int[] result = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
while (!deque.isEmpty() && deque.peekFirst() < i - k + 1) {
deque.pollFirst();
}
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
deque.offerLast(i);
if (i >= k - 1) {
result[i - k + 1] = nums[deque.peekFirst()];
}
}
return result;
}
3. Number of Islands (LeetCode 200)
public int numIslands(char[][] grid) {
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == '1') {
bfs(grid, i, j);
count++;
}
}
}
return count;
}
private void bfs(char[][] grid, int row, int col) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{row, col});
grid[row][col] = '0';
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
while (!queue.isEmpty()) {
int[] cell = queue.poll();
for (int[] dir : dirs) {
int r = cell[0] + dir[0], c = cell[1] + dir[1];
if (r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && grid[r][c] == '1') {
queue.offer(new int[]{r, c});
grid[r][c] = '0';
}
}
}
}
Queue vs Stack
| Feature | Queue | Stack |
|---|---|---|
| Principle | FIFO | LIFO |
| Access | Front and Rear | Top only |
| Use Case | BFS | DFS |
| Real World | Line at store | Stack of plates |
Practice Problems
Given the root of a binary tree, return the level order traversal of its nodes' values.
Example:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]
Level by level traversal.
Optimal Solution — O(n) time, O(n) space
BFS with queue
class Solution {
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 size = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; 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;
}
}Edge Cases:
- Empty tree
- Single node
- Unbalanced tree
Implement a FIFO queue using only two stacks.
Example:
Input: MyQueue q = new MyQueue(); q.push(1); q.push(2); q.peek(); q.pop();
Output: 1, 1
FIFO order maintained.
Optimal Solution — Amortized O(1) time, O(n) space
Amortized O(1) using two stacks
class MyQueue {
Stack<Integer> input = new Stack<>();
Stack<Integer> output = new Stack<>();
public void push(int x) {
input.push(x);
}
public int pop() {
if (output.isEmpty()) {
while (!input.isEmpty()) output.push(input.pop());
}
return output.pop();
}
public int peek() {
if (output.isEmpty()) {
while (!input.isEmpty()) output.push(input.pop());
}
return output.peek();
}
}Edge Cases:
- Pop when empty
- Interleaved push/pop
Given an m x n grid of '1's (land) and '0's (water), count the number of islands.
Example:
Input: grid = [["1","1","0"],["1","1","0"],["0","0","1"]]
Output: 2
Two separate islands.
Optimal Solution — O(m*n) time, O(min(m,n)) space
BFS/DFS to mark visited
class Solution {
public int numIslands(char[][] grid) {
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == '1') {
bfs(grid, i, j);
count++;
}
}
}
return count;
}
private void bfs(char[][] grid, int r, int c) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{r, c});
grid[r][c] = '0';
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
while (!queue.isEmpty()) {
int[] cell = queue.poll();
for (int[] d : dirs) {
int nr = cell[0]+d[0], nc = cell[1]+d[1];
if (nr>=0 && nr<grid.length && nc>=0 && nc<grid[0].length && grid[nr][nc]=='1') {
grid[nr][nc] = '0';
queue.offer(new int[]{nr, nc});
}
}
}
}
}Edge Cases:
- All water
- All land
- Single cell
Quiz
1. What principle does a queue follow?
2. Which algorithm uses a queue?
3. What is the primary purpose of Queue?
4. What is a common mistake when implementing Queue?
Flashcards
Question
What is FIFO?
Click to reveal answer
Answer
First In First Out - the first element added is the first to be removed.
Question
When should I use a queue?
Click to reveal answer
Answer
For BFS traversal, sliding window, and processing items in order.
Question
What is Queue?
Click to reveal answer
Answer
Queue is a key concept in software engineering.
Question
When to use Queue?
Click to reveal answer
Answer
Use Queue when building production systems that require reliability, scalability, and maintainability.
Question
Queue best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.Queue is FIFO
- 2.All operations are O(1)
- 3.Use for BFS and level-order traversal
- 4.Deque is preferred over LinkedList
Interview Tips
- •Explain FIFO principle
- •Discuss BFS vs DFS tradeoffs
- •Mention priority queue when ordering matters
Cheat Sheet
Queue Cheat Sheet
Operations: enqueue, dequeue, peek, isEmpty - all O(1)
Use Cases: BFS, scheduling, buffering, sliding window
Java: Use Deque interface with ArrayDeque
Pattern: Add neighbors to queue, process front