Alucaard
Alucaard

Reputation: 1

Rotate a linked list: understanding shallow/deep copy

I am looking that LeetCode problem 61. Rotate List:

Given the head of a linked list, rotate the list to the right by k places.

Example 1

enter image description here

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

Answers (1)

trincot
trincot

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.

Iteration #1

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.

Iteration #2

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

Related Questions