Algorithm Templates: Queue
Queues are one of the most versatile data structures in algorithm problems. This page collects ready-to-use Java templates for every queue variant you’ll encounter on LeetCode — from the basic FIFO queue used in BFS to monotonic queues, priority queues, and deques. Each section includes the template code and a curated problem list so you can practice immediately.
See also Graph and Data Structures (monotonic queue).
Queue = First-In-First-Out (FIFO). Use a queue whenever you need to process elements in the order they arrived — most commonly in BFS. A deque (double-ended queue) lets you push/pop from both ends.
- Beginner’s Guide: LeetCode Beginner’s Guide
Summary
| Pattern | Signal Phrases | Key Idea | |—|—|—| | BFS Queue | “shortest path”, “level order” | Process nodes level by level | | Monotonic Queue | “sliding window max/min” | Maintain decreasing/increasing order | | Priority Queue | “k-th largest”, “merge k sorted” | Auto-sorted by priority | | Circular Queue | “circular buffer”, “design queue” | Wrap-around with modulo | | Deque | “sliding window”, “both ends” | Push/pop from front and back |
Contents
- Basic Queue Operations
- BFS with Queue
- Monotonic Queue
- Priority Queue
- Circular Queue
- Double-ended Queue (Deque)
Basic Queue Operations
When to use: any problem requiring FIFO ordering, or when implementing a queue from scratch (e.g., using two stacks).
Implement Queue using Stacks
| ID | Title | Link | Solution |
|---|---|---|---|
| 232 | Implement Queue using Stacks | Link | - |
// import java.util.*;
// Standard queue operations
Queue<Integer> q = new LinkedList<>();
q.offer(1); // Enqueue
q.get(0); // Peek front
q.get(q.size() - 1); // Peek back
q.poll(); // Dequeue
q.length == 0; // Check if empty
q.size(); // Get size
Implement Queue using Stacks
// import java.util.*;
class MyQueue {
Deque<Integer> input, output;
void push(int x) {
input.offer(x);
}
int pop() {
peek();
int val = output.peek();
output.poll();
return val;
}
int peek() {
if (output.length == 0) {
while (!input.isEmpty()) {
output.offer(input.peek());
input.poll();
}
}
return output.peek();
}
boolean empty() {
return input.length == 0 && output.length == 0;
}
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 232 | Implement Queue using Stacks | Link | - |
BFS with Queue
When to use: “shortest path in unweighted graph”, “level order traversal”, “minimum steps”, or any problem that explores neighbors layer by layer.
Queue is essential for Breadth-First Search (level-order traversal).
| ID | Title | Link | Solution |
|---|---|---|---|
| 102 | Binary Tree Level Order Traversal | Link | - |
| 107 | Binary Tree Level Order Traversal II | Link | - |
// import java.util.*;
// BFS on graph
static void bfs(int[][] graph, int start) {
Queue<Integer> q = new LinkedList<>();
boolean[]visited(graph.size(), false);
q.offer(start);
visited[start] = true;
while (!q.isEmpty()) {
int node = q.get(0);
q.poll();
// Process node
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.offer(neighbor);
}
}
}
}
// Level-order traversal (BFS on tree)
int[][] levelOrder(TreeNode root) {
List<int[]> result = new ArrayList<>();
if (!root) return result;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; ++i) {
TreeNode node = q.get(0);
q.poll();
level.add(node.val);
if (node.left) q.offer(node.left);
if (node.right) q.offer(node.right);
}
result.add(level);
}
return result;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 102 | Binary Tree Level Order Traversal | Link | - |
| 107 | Binary Tree Level Order Traversal II | Link | - |
Monotonic Queue
When to use: “sliding window maximum/minimum”, or when you need the max/min of every window of size k in O(n) total.
Maintain queue with monotonic property (increasing or decreasing).
| ID | Title | Link | Solution |
|---|---|---|---|
| 239 | Sliding Window Maximum | Link | Solution |
| 1438 | Longest Continuous Subarray With Absolute Diff <= Limit | Link | - |
// import java.util.*;
// Monotonic decreasing queue (for sliding window maximum)
class MonotonicQueue {
ArrayDeque<Integer> dq = new ArrayDeque<>();
void push(int val) {
// Remove elements smaller than val
while (!dq.isEmpty() && dq.get(dq.size() - 1) < val) {
dq.removeLast();
}
dq.add(val);
}
void pop(int val) {
if (!dq.isEmpty() && dq.get(0) == val) {
dq.removeFirst();
}
}
int Math.max() {
return dq.get(0);
}
}
// Sliding Window Maximum
int[]maxSlidingWindow(int[] nums, int k) {
MonotonicQueue mq;
List<Integer> result = new ArrayList<>();
for (int i = 0; i < nums.length; ++i) {
if (i < k - 1) {
mq.offer(nums[i]);
} else {
mq.offer(nums[i]);
result.add(mq.Math.max());
mq.pop(nums[i - k + 1]);
}
}
return result;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 239 | Sliding Window Maximum | Link | Solution |
| 1438 | Longest Continuous Subarray With Absolute Diff <= Limit | Link | - |
Priority Queue
When to use: “k-th largest/smallest”, “merge k sorted lists”, “top k elements”, “schedule tasks by priority”, or any problem needing efficient access to the current extreme value.
Priority queue (heap) for maintaining order.
K-way Merge
Top K Elements
| ID | Title | Link | Solution |
|---|---|---|---|
| 23 | Merge k Sorted Lists | Link | - |
| 347 | Top K Frequent Elements | Link | Solution |
| 295 | Find Median from Data Stream | Link | - |
| 215 | Kth Largest Element in an Array | Link | - |
| 973 | K Closest Points to Origin | Link | - |
| 253 | Meeting Rooms II | Link | Solution |
| 378 | Kth Smallest Element in a Sorted Matrix | Link | - |
| 703 | Kth Largest Element in a Stream | Link | - |
| 767 | Reorganize String | Link | - |
| 1046 | Last Stone Weight | Link | - |
| 1167 | Minimum Cost to Connect Sticks | Link | - |
| 621 | Task Scheduler | Link | - |
| 743 | Network Delay Time | Link | - |
| 787 | Cheapest Flights Within K Stops | Link | - |
// import java.util.*;
// Max heap (default)
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>();
// Min heap
PriorityQueue<Integer> minHeap;
// Custom comparator using class
class Compare {
}
PriorityQueue<int[]> pq;
// Custom comparator using lambda operator
PriorityQueue<int[]> pq(cmp);
// Lambda example: Min heap by distance (for Dijkstra's algorithm)
- min heap by distance
}
PriorityQueue<int[]> pq(distCmp);
K-way Merge
// Merge k sorted lists using priority queue
ListNode mergeKLists(ListNode[] lists) {
priority_queue<ListNode, ListNode[], > pq(cmp);
for (ListNode list : lists) {
if (list) pq.offer(list);
}
ListNode dummy = new ListNode = new new(0);
ListNode cur = dummy;
while (!pq.isEmpty()) {
ListNode node = pq.peek();
pq.poll();
cur.next = node;
cur = cur.next;
if (node.next) pq.offer(node.next);
}
return dummy.next;
}
Top K Elements
// import java.util.*;
// Find top k frequent elements
int[]topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> freq = new HashMap<Integer, Integer>();
for (int num : nums) freq.put(num, freq.getOrDefault(num, 0) + 1);
PriorityQueue<int[]> pq;
for (var e : freq.entrySet()) {
pq.offer(new int[] {count, num});
if (pq.size() > k) pq.poll();
}
List<Integer> result = new ArrayList<>();
while (!pq.isEmpty()) {
result.add(pq.peek().second);
pq.poll();
}
return result;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 23 | Merge k Sorted Lists | Link | - |
| 347 | Top K Frequent Elements | Link | Solution |
| 295 | Find Median from Data Stream | Link | - |
| 215 | Kth Largest Element in an Array | Link | - |
| 973 | K Closest Points to Origin | Link | - |
| 253 | Meeting Rooms II | Link | Solution |
| 378 | Kth Smallest Element in a Sorted Matrix | Link | - |
| 703 | Kth Largest Element in a Stream | Link | - |
| 767 | Reorganize String | Link | - |
| 1046 | Last Stone Weight | Link | - |
| 1167 | Minimum Cost to Connect Sticks | Link | - |
| 621 | Task Scheduler | Link | - |
| 743 | Network Delay Time | Link | - |
| 787 | Cheapest Flights Within K Stops | Link | - |
Circular Queue
When to use: “design a circular buffer”, “design a queue with fixed capacity”, or when you need wrap-around behavior with modulo arithmetic.
| ID | Title | Link | Solution |
|---|---|---|---|
| 622 | Design Circular Queue | Link | - |
class MyCircularQueue {
List<Integer> data = new ArrayList<>();
int head, tail, size, capacity;
MyCircularQueue(int k) {}
boolean enQueue(int value) {
if (isFull()) return false;
data[tail] = value;
tail = (tail + 1) % capacity;
size++;
return true;
}
boolean deQueue() {
if (isEmpty()) return false;
head = (head + 1) % capacity;
size--;
return true;
}
int Front() {
return isEmpty() ? -1 : data[head];
}
int Rear() {
return isEmpty() ? -1 : data[(tail - 1 + capacity) % capacity];
}
boolean isEmpty() {
return size == 0;
}
boolean isFull() {
return size == capacity;
}
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 622 | Design Circular Queue | Link | - |
Double-ended Queue (Deque)
When to use: “sliding window” problems where you need to push/pop from both front and back, or when maintaining sorted order in a window by index.
Sliding Window with Deque
Two Deques Pattern (Middle Element Access)
Use two deques to efficiently access middle elements in a queue.
Key points:
- Split queue into two halves:
front_cacheandback_cache - Maintain balance:
front_cache.size() <= back_cache.size() <= front_cache.size() + 1 - Middle element is
front_cache.back()(if sizes equal) orback_cache.front()(if back_cache larger) - Rebalance after each modification
| ID | Title | Link | Solution |
|---|---|---|---|
| 239 | Sliding Window Maximum | Link | Solution |
| 1670 | Design Front Middle Back Queue | Link | Solution |
// import java.util.*;
ArrayDeque<Integer> dq = new ArrayDeque<>();
dq.push_front(1); // Add to front
dq.add(2); // Add to back
dq.removeFirst(); // Remove from front
dq.removeLast(); // Remove from back
dq.get(0); // Access front
dq.get(dq.size() - 1); // Access back
Sliding Window with Deque
// import java.util.*;
// Sliding window maximum using deque
int[]maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> dq = new ArrayDeque<>();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < nums.length; ++i) {
// Remove indices outside window
while (!dq.isEmpty() && dq.get(0) <= i - k) {
dq.removeFirst();
}
// Remove indices with smaller values
while (!dq.isEmpty() && nums[dq.get(dq.size() - 1)] <= nums[i]) {
dq.removeLast();
}
dq.add(i);
if (i >= k - 1) {
result.add(nums[dq.get(0)]);
}
}
return result;
}
Two Deques Pattern (Middle Element Access)
Use two deques to efficiently access middle elements in a queue.
// import java.util.*;
// Front Middle Back Queue: Two deques with rebalancing
class FrontMiddleBackQueue {
ArrayDeque<Integer> front_cache, back_cache;
void rebalance() {
// Maintain: front_cache.size() <= back_cache.size() <= front_cache.size() + 1
while(front_cache.size() > back_cache.size()) {
back_cache.push_front(front_cache.get(front_cache.size() - 1));
front_cache.removeLast();
}
while(back_cache.size() > front_cache.size() + 1) {
front_cache.add(back_cache.get(0));
back_cache.removeFirst();
}
}
void pushMiddle(int val) {
front_cache.add(val);
rebalance();
}
int popMiddle() {
if(front_cache.length == 0 && back_cache.length == 0) return -1;
if(front_cache.size() == back_cache.size()) {
int val = front_cache.get(front_cache.size() - 1);
front_cache.removeLast();
return val;
} else {
int val = back_cache.get(0);
back_cache.removeFirst();
return val;
}
}
}
Key points:
- Split queue into two halves:
front_cacheandback_cache - Maintain balance:
front_cache.size() <= back_cache.size() <= front_cache.size() + 1 - Middle element is
front_cache.back()(if sizes equal) orback_cache.front()(if back_cache larger) - Rebalance after each modification
| ID | Title | Link | Solution |
|---|---|---|---|
| 239 | Sliding Window Maximum | Link | Solution |
| 1670 | Design Front Middle Back Queue | Link | Solution |
More templates
- Data structures (monotonic queue): Data Structures & Core Algorithms
- BFS, Graph: BFS, Graph
- Master index: Categories & Templates