Stacks & Queues · 28 of 38
Reverse the first K elements of a queue
Turn around only the first few kids in a waiting line and keep everyone else where they were.
- Simple way
- time O(n)
room O(n) - Clever way
- time O(n)
room O(k)
The problem, simply
You get a queue, a waiting line, and a number k. Reverse the order of the first k items. The other items must stay behind them, in the same order as before.
You may only use queue moves: take from the front, add at the back, look at the front, and ask for the size. You may also use a stack.
A story to remember it
Picture it
Reverse only the first 3 of 5. The last two keep their place and order.
- answer
- path
Examples
Half the line
- In
queue = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 5- Out
[5, 4, 3, 2, 1, 6, 7, 8, 9, 10]
The first five flip. 6 to 10 stay as they were.
The animation's line
- In
queue = [10, 20, 30, 40, 50], k = 3- Out
[30, 20, 10, 40, 50]
Three go up the ladder and come down reversed. 40 and 50 walk around behind them.
k equals the size
- In
queue = [1, 2, 3], k = 3- Out
[3, 2, 1]
The whole queue is reversed and there is nobody left to walk around.
k is 1 or 0
- In
queue = [4, 5, 6], k = 1 or k = 0- Out
[4, 5, 6]
Reversing one item, or none, changes nothing.
k too big
- In
queue = [1, 2], k = 5- Out
[1, 2] (or an error)
There are not five items to reverse. Leave the queue alone or report an error; agree on this with the interviewer.
Way 1: the simple way
Copy everything out into a list, flip the first k boxes of the list, and copy it all back.
- Move all
nitems from the queue into a list. - Reverse the first
kpositions of the list. - Add every item of the list back into the queue.
Way 1 pours the whole queue into a list, flips the first 3 boxes of the list, then pours it all back.
- just added
import java.util.*;
class Solution {
public void reverseFirstK(Queue<Integer> q, int k) {
if (k < 0 || k > q.size()) return;
List<Integer> all = new ArrayList<>();
while (!q.isEmpty()) all.add(q.poll()); // pour everything out
Collections.reverse(all.subList(0, k)); // flip the first k
for (int x : all) q.offer(x); // pour it back
}
}How long it takes: every item moves out and back once, O(n). Extra room: the list holds all n items, O(n).
Way 2: the clever way
Only the first k items need a helper. A stack reverses them, and a rotation puts the rest behind them.
- Take
kitems from the front and push them on a stack. - Pop them all and add each to the back of the queue. They are now at the back, reversed.
- Move the other
n - kitems from the front to the back, one by one.
Stack the first k, put them back, then rotate the rest
01 / 10
The queue is 10, 20, 30, 40, 50 and k is 3. The first three, 10, 20, 30, must come out reversed.
- k
- 3
- n
- 5
- checking
- done
- answer
- path
- just added
import java.util.*;
class Solution {
public void reverseFirstK(Queue<Integer> q, int k) {
int n = q.size();
if (k < 0 || k > n) return;
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < k; i++) stack.push(q.poll()); // 1. first k up the ladder
while (!stack.isEmpty()) q.offer(stack.pop()); // 2. down again, reversed, to the back
for (int i = 0; i < n - k; i++) q.offer(q.poll()); // 3. the rest walk around behind them
}
}How long it takes: k pushes, k pops, and n - k rotations, O(n). Extra room: the stack holds only k items, O(k).
Another way: recursion instead of the stack
The call stack can play the ladder. Hold the front item, reverse the next k - 1 items with a recursive call, then add the held item at the back. After that, rotate the other n - k items.
import java.util.*;
class Solution {
public void reverseFirstK(Queue<Integer> q, int k) {
int n = q.size();
if (k < 0 || k > n) return;
sendReversed(q, k); // the first k go to the back, reversed
for (int i = 0; i < n - k; i++) q.offer(q.poll());
}
private void sendReversed(Queue<Integer> q, int k) {
if (k == 0) return;
int front = q.poll(); // hold this one
sendReversed(q, k - 1); // the next k - 1 go to the back first, reversed
q.offer(front); // then this one, so it lands after them
}
}Same O(n) time and O(k) room, but the room is the call stack, so a huge k can overflow it.
Watch out for
- Rotating
norktimes instead ofn - k. Saven = q.size()before you change the queue, then rotate exactlyn - ktimes. - Not checking
k. Akbigger than the queue makespoll()returnnull, which crashes when unboxed. A negativekmakes no sense. - Reading
q.size()inside the rotation loop. It does not change during a rotation here, but savingnfirst avoids confusion.
What interviewers ask next
- Reverse the whole queue: that is
k = n, and step 3 does nothing. - Reverse the queue in groups of
k: repeat steps 1 and 2 for every full group. Each group goes to the back in turn, so the groups keep their order. Rotate any leftover items at the end. - Reverse only the last
kitems: rotate the firstn - kitems to the back first, then reverse the nextkwith the stack. - Can you do it with no stack and no recursion? Not with plain queue moves, because a rotation never changes the circular order of the items.
Remember this
Grown-up words: the waiting line is a queue, the ladder is a stack, walking from front to back is a rotation, and the recursion version uses the call stack as the helper.