Linked List · 25 of 36
Rotate a Doubly Linked list in group of Given Size
Cut a two way chain into groups of k, turn each group around (the last short group too), and hook every group to its neighbors in both directions.
- Simple way
- time O(n)
room O(k) - Clever way
- time O(n)
room O(1)
The problem, simply
You get a doubly linked list, where every box has a next arrow forward and a prev arrow back, and a number k.
Walk the chain in groups of k boxes and turn each group around. The groups stay in their old order. If the last group has fewer than k boxes, turn it around too. Every next and every prev must be right at the end, and the new head must have prev = null.
The sheet calls this "rotate in groups", but the task it points to is turning each group around (reversing it), as in the examples.
A story to remember it
Picture it
A doubly linked list with k = 3. The groups are 1 2 3, then 4 5 6, then the short group 7 8.
- checking
- path
Examples
A normal case
- In
1 <-> 2 <-> 3 <-> 4 <-> 5 <-> 6 <-> 7 <-> 8, k = 3- Out
3 <-> 2 <-> 1 <-> 6 <-> 5 <-> 4 <-> 8 <-> 7
The short last group 7 8 is also turned around.
Pairs
- In
1 <-> 2 <-> 3 <-> 4 <-> 5, k = 2- Out
2 <-> 1 <-> 4 <-> 3 <-> 5
The last group is only box 5, and one box turned around is the same box.
k bigger than the chain
- In
1 <-> 2 <-> 3, k = 5- Out
3 <-> 2 <-> 1
The whole chain is one short group, so this is a plain reversal.
k is 1
- In
4 <-> 9 <-> 2, k = 1- Out
4 <-> 9 <-> 2
Groups of one box do not change anything.
Way 1: the simple way
Do not touch the arrows. For each group, copy its numbers into a small list, turn the list around, and write the numbers back into the same boxes.
- Start at the head.
- Copy up to
knumbers into a small list and remember where the group started. - Turn the small list around and write the numbers back into the group's boxes.
- Go on with the next group.
The second group 4 5 6 is copied out, turned around, and is about to be written back into the same three boxes.
- looking now
- done
- just added
import java.util.*;
class Solution {
public Node reverseInGroups(Node head, int k) {
Node curr = head;
while (curr != null) {
Node groupStart = curr;
List<Integer> nums = new ArrayList<>();
for (int i = 0; i < k && curr != null; i++) { // copy up to k numbers
nums.add(curr.data);
curr = curr.next;
}
Collections.reverse(nums);
Node w = groupStart;
for (int x : nums) { w.data = x; w = w.next; } // write them back
}
return head;
}
}How long it takes: every box is read once and written once, O(n). Extra room: the small list holds one group, O(k). Interviewers usually want the boxes moved, not the numbers.
Way 2: the clever way
Turn the boxes themselves around, one group at a time, and stitch the groups together.
currwalks the chain.prevTailis the last box of the finished part,nullat first.- Remember
groupFirst = curr. Turn up tokboxes around: for each box, savenext, pointnextback toprev, and pointprevforward to the savednext. - Now
previs the group's new first box andgroupFirstis its new last box. - Stitch: if this is the first group, it gives the new head. Otherwise
prevTail.next = prev. In both cases setprev.prev = prevTail. - Move
prevTailtogroupFirstand keep going whilecurris notnull.
Turn each group of 3 around and stitch the gaps
01 / 09
Start. curr is on box 1. Nothing is finished yet, so prevTail is null.
- k
- 3
- looking now
- done
- answer
- path
- just added
class Solution {
public Node reverseInGroups(Node head, int k) {
if (head == null || k <= 1) return head;
Node newHead = null, prevTail = null, curr = head;
while (curr != null) {
Node groupFirst = curr, prev = null;
for (int i = 0; i < k && curr != null; i++) { // turn up to k boxes around
Node next = curr.next;
curr.next = prev; // look back
curr.prev = next; // the old next is now behind me
prev = curr;
curr = next;
}
// prev is the group's new first box, groupFirst its new last box
if (newHead == null) newHead = prev;
else prevTail.next = prev; // stitch forward
prev.prev = prevTail; // stitch backward (null for the first group)
prevTail = groupFirst;
}
return newHead;
}
}How long it takes: every box is flipped once, O(n). Extra room: a few fingers, O(1). The last box of the last group already has next = null, because each group starts flipping with prev = null.
Watch out for
- Stitching only
nextbetween groups. Walking backwards from the tail then jumps to the wrong box. Fix bothprevTail.nextandprev.prev. - Moving
prevTailtoprev. After the flip,previs the front of the group. The back isgroupFirst. - Read the problem: some versions leave the short last group alone. Then count
kboxes first and stop if there are not enough, as in the singly linked version.
What interviewers ask next
- How is this different from the singly linked version? Same groups, but every flip and every stitch must fix two arrows, and the head's
prevmust end asnull. - Rotate each group instead of reversing it: in each block of
k, move the lastdboxes to the front of the block. Cut the block, find itsdth box from the end, and relink the block's two pieces in swapped order. - Do it with recursion: flip the first group, then let a helper do the rest and stitch the group's last box to the helper's head in both directions. It costs
O(n/k)stack room. - How do you test it? Walk forward from the head and backward from the tail. The two readings must be exact mirrors, and the head's
prevand the tail'snextmust benull.
Remember this
Grown-up words: the dance line is a doubly linked list, each kid is a node with prev and next pointers, turning a little line around is reversing a group, and stitching the gaps is relinking the group boundaries.