Linked List · 24 of 36
Rotate Doubly Linked list by N nodes
Move the first N boxes of a two way chain to its end by joining the chain into a ring and cutting it at the right spot.
- Simple way
- time O(N * n)
room O(1) - Clever way
- time O(n)
room O(1)
The problem, simply
You get a doubly linked list (every box has a next arrow and a prev arrow) and a number N. Rotate it to the left by N: the first N boxes move, in the same order, to the end of the chain.
For example 10 20 30 40 50 60 with N = 2 becomes 30 40 50 60 10 20. Give back the new head, with prev and next correct everywhere. In this page n is the number of boxes and N is how far to rotate.
A story to remember it
Picture it
Six boxes and N = 2. The first two boxes, 10 and 20, will move to the end.
- checking
Examples
A normal case
- In
10 <-> 20 <-> 30 <-> 40 <-> 50 <-> 60, N = 2- Out
30 <-> 40 <-> 50 <-> 60 <-> 10 <-> 20
30 is the new head. 20 is the new tail.
Letters
- In
a <-> b <-> c <-> d <-> e, N = 2- Out
c <-> d <-> e <-> a <-> b
The same idea with letters, as in the classic version of this problem.
N bigger than the chain
- In
1 <-> 2 <-> 3, N = 4- Out
2 <-> 3 <-> 1
Rotating by 3 brings the chain back to where it started, so rotating by 4 is the same as rotating by 4 mod 3 = 1.
N is a multiple of the length
- In
1 <-> 2 <-> 3, N = 3- Out
1 <-> 2 <-> 3
Nothing changes. Return early.
One box or empty
- In
7, N = 5- Out
7
There is nothing to move around.
Way 1: the simple way
Rotate one step at a time, N times. One step means: take the head off, walk to the tail, and hook the old head after it.
- Count the boxes and shrink
NtoN % n. - Repeat
Ntimes: unhook the head, fix the new head'sprevtonull, walk to the tail, hook the old head there with both arrows, and set itsnexttonull.
After one single step: 10 moved from the front to the back. One more step will move 20.
- just added
class Solution {
public Node rotate(Node head, int N) {
if (head == null || head.next == null) return head;
int n = 0;
for (Node t = head; t != null; t = t.next) n++;
N %= n;
for (int step = 0; step < N; step++) {
Node first = head;
head = head.next; // second box becomes the head
head.prev = null;
Node tail = head;
while (tail.next != null) tail = tail.next; // walk to the end
tail.next = first; // hook the old head at the back
first.prev = tail;
first.next = null;
}
return head;
}
}How long it takes: each of the N steps walks to the tail, about n boxes, so O(N * n). Extra room: O(1).
Way 2: the clever way
Tie the bracelet and snip once.
- Walk to the tail and count the boxes
non the way. - Shrink
NtoN % n. If it is 0, give back the head. - Walk
N - 1steps from the head to findnewTail, the box that will be last. The box after it isnewHead. - Tie the ring:
tail.next = headandhead.prev = tail. - Snip:
newTail.next = nullandnewHead.prev = null. Give backnewHead.
Tie a ring, then snip after the Nth box
01 / 05
The chain has loose ends at 10 and 60. N is 2.
- N
- 2
- looking now
- checking
- seen
- done
- answer
- just added
class Solution {
public Node rotate(Node head, int N) {
if (head == null || head.next == null) return head;
int n = 1;
Node tail = head;
while (tail.next != null) { tail = tail.next; n++; } // find tail and length
N %= n;
if (N == 0) return head;
Node newTail = head;
for (int i = 1; i < N; i++) newTail = newTail.next; // the Nth box
Node newHead = newTail.next;
tail.next = head; // tie the ring
head.prev = tail;
newTail.next = null; // snip
newHead.prev = null;
return newHead;
}
}How long it takes: one walk to the tail and at most one more partial walk, O(n). Extra room: O(1). Only four arrows change, no matter how big N is.
Watch out for
- Fix both arrows at the knot and at the snip. A doubly list with only
nextfixed reads fine forward but breaks when walked backward. - Left or right? This problem moves the first
Nboxes to the back (a left rotation). Rotating right byk(LeetCode 61) is the same as rotating left byn - k % n. - Empty chain and one box: return at once.
What interviewers ask next
- Rotate right by
kinstead. Find the boxn - k % nfrom the start and cut after it, or cut after the(k % n)th box from the end using the two finger gap trick. - Do it for a singly linked list. Same steps, minus the
prevarrows. - What if
Ncan be huge, like a billion?N % nmakes it the same work as a smallN. - Rotate each block of
kboxes byd: cut the chain into blocks, rotate each block with this ring and snip trick, and stitch the blocks back together.
Remember this
Grown-up words: the bracelet is a circular linked list, the beads are nodes with prev and next pointers, and moving the first N boxes to the back is a left rotation.