Reputation: 1
I am looking that LeetCode problem 61. Rotate List:
Given the
head
of a linked list, rotate the list to the right byk
places.Example 1
I don't understand why we have to do tail.next = None
at the very end. Also, we did tail = head
, so why are we not making the last node of head = None
?
I was trying to solve the question, but could not solve it and hence I took a reference, but I am not able to understand it either.
NB: I understand that we made a circular linked list here.
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head:
return head
# calculate size of the list and close it in a cycle
tail = head
size = 1
while tail.next:
tail = tail.next
size += 1
tail.next = head
# calculate required number of steps, do them and break the cycle
for i in range(size - k % size):
tail = head
head = head.next
tail.next = None
return head
Upvotes: 0
Views: 79
Reputation: 350770
No nodes are copied here (not shallow, not deep). Only their references are. It may help to visualise this. Let's say we have a linked list with 5 values: 1, 2, 3, 4, 5, and we have already made it circular:
head
│
▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
We already derived that size
is 5. Now let's say k
is 3. That makes the loop iterate size - k % size
times, which is 2 times.
The first iteration makes tail
to reference the same node as head
:
tail head
│ │
▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
Then head
takes on the reference that head.next
has:
tail head
│ │
▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
And here we see an invariant: at the end of each iteration, head
will reference the node that follows after tail
.
This iteration also makes tail
to reference the same node as head
:
tail head
│ │
▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
head
again takes on the reference that head.next
has:
tail head
│ │
▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
Now the list is almost ready. We just need to remove the cycle. This means we break the list between tail
and head
. In other words, the next
reference of the tail node must be set to None
. Therefore we need to execute tail.next = None
:
tail head
│ │
▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: None │ │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
The function then returns the head
reference and both local names head
and tail
are now out of scope.
(returned)
│
▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 1 │ │ val: 2 │ │ val: 3 │ │ val: 4 │ │ val: 5 │
│ next: ───────► │ next: None │ │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
This list is just a different visual representation of this one:
(returned)
│
▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ val: 3 │ │ val: 4 │ │ val: 5 │ │ val: 1 │ │ val: 2 │
│ next: ───────► │ next: ───────► │ next: ───────► │ next: ───────► │ next: ──┐ │
└────────────┘ └────────────┘ └────────────┘ └────────────┘ └─────────│──┘
▲ │
└───────────────────────────────────────────────────────────────────────┘
Hope this clarifies it.
Upvotes: 0