Linked List · 2 of 36
Reverse a Linked List in group of Given Size
Cut a chain of boxes into groups of k, turn each full group around, and hook the groups back together in the same order.
- Simple way
- time O(n)
room O(n/k) - Clever way
- time O(n)
room O(1)
The problem, simply
You get a linked list and a number k. Walk the chain in groups of k boxes. Turn each group around, but keep the groups themselves in their old order.
If the last group has fewer than k boxes, leave it as it is. Give back the new first box.
There is a second version of this problem (the GeeksforGeeks one) where the short last group is turned around too. The code changes in one line, shown in "Watch out for".
A story to remember it
Picture it
Seven boxes and k = 3. Groups: 1 2 3, then 4 5 6, then 7 alone. Only full groups get turned around.
- checking
- path
- ignored
Examples
A normal case
- In
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7, k = 3- Out
3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 7
Two full groups are turned around. Box 7 is a short group, so it stays.
Pairs
- In
1 -> 2 -> 3 -> 4 -> 5, k = 2- Out
2 -> 1 -> 4 -> 3 -> 5
This is the "swap nodes in pairs" problem in disguise.
k equals the length
- In
1 -> 2 -> 3, k = 3- Out
3 -> 2 -> 1
One group, the whole chain. Same as a plain reversal.
k is 1
- In
1 -> 2 -> 3, k = 1- Out
1 -> 2 -> 3
A group of one box turned around is the same box.
The other version
- In
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8, k = 3- Out
3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 8 -> 7
In the version where the short last group is also turned around, 7 and 8 become 8 and 7. With the main rule they would stay 7, 8.
Way 1: the simple way
Let a helper handle the rest of the chain. This is recursion.
- Check that there are at least
kboxes fromhead. If not, returnheadunchanged. - Turn the first
kboxes around with the three fingersprev,curr,next. - The old first box is now the end of this group. Hook it to whatever the helper returns for the rest of the chain.
- Return the new first box of this group.
The first group is turned around. Box 1, its new end, waits for the helper to sort out 4 5 6 7.
- looking now
- done
- ignored
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode probe = head;
for (int i = 0; i < k; i++) { // are there k boxes?
if (probe == null) return head; // short group: leave it
probe = probe.next;
}
ListNode prev = null, curr = head;
for (int i = 0; i < k; i++) { // turn this group around
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head.next = reverseKGroup(curr, k); // old first box hooks to the rest
return prev; // new first box of this group
}
}How long it takes: every box is counted once and flipped once, O(n). Extra room: one waiting helper per group on the call stack, O(n/k). For a long chain and a small k, that stack can get deep.
Way 2: the clever way
Do the same with a loop and a fake box in front, the dummy. The finger groupPrev always sits on the box just before the group we are about to flip.
- Put a dummy box
Dbefore the head.groupPrev = D. - Walk
ksteps fromgroupPrevto findkth, the last box of the group. If you fall off the chain, stop. - Remember
groupNext = kth.next, the first box after the group. - Flip the group with
prevstarting atgroupNext, so the old first box ends up pointing togroupNext. - Hook
groupPrev.next = kth(the new first box), and movegroupPrevto the old first box (the new last box). - Repeat. The answer is
D.next.
Flip groups of 3, one group at a time
01 / 09
Put a dummy box D before the head. groupPrev sits on D.
- k
- 3
- checking
- done
- answer
- path
- just added
- ignored
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0, head);
ListNode groupPrev = dummy;
while (true) {
ListNode kth = groupPrev;
for (int i = 0; i < k && kth != null; i++) kth = kth.next; // find the group's last box
if (kth == null) break; // short group: done
ListNode groupNext = kth.next;
ListNode prev = groupNext, curr = groupPrev.next; // flip inside the group
while (curr != groupNext) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
ListNode oldFirst = groupPrev.next;
groupPrev.next = kth; // hook the new first box
groupPrev = oldFirst; // the old first box is now the group's end
}
return dummy.next;
}
}How long it takes: each box is stepped over once when counting and once when flipping, O(n). Extra room: a handful of fingers and one dummy box, O(1).
Watch out for
- Starting
prevatnullinside a group cuts the chain. Start it atgroupNextso the flipped group stays hooked to the rest. - Moving
groupPrevtokth. After the flip,kthis the front of the group.groupPrevmust go to the old first box, the new back. - The other version (turn the short last group around too): in Way 1, drop the "are there k boxes" check and flip while
curr != nullfor at mostksteps. In Way 2, whenkthisnull, flip the leftover boxes once and stop. kof 1 or an empty chain: both ways return the chain unchanged.
What interviewers ask next
- Swap nodes in pairs (LeetCode 24). It is this problem with
k = 2. - Reverse only between positions
mandn(LeetCode 92). Walk to boxm - 1, then flip one group of sizen - m + 1the same way. - Reverse alternate groups: flip a group of
k, then skip the nextkboxes, and repeat. Add a skip loop after each hook. - Why is the iterative way better in production? No deep call stack, so a chain of a million boxes with
k = 2does not overflow. - What about a doubly linked list? Same groups, but inside a group you swap
prevandnext, and you also fix theprevof the box after each group.
Remember this
Grown-up words: the wagons are nodes, flipping is reversing the next pointers, the fake front wagon is a dummy node, and the helpers waiting on each other are the recursion call stack.