Linked List Part 5: Rotation
Rotating a linked list involves shifting its elements to the right by a specified number of places. This can be particularly useful in various applications, such as implementing circular buffers or rotating elements in a queue. We will break down the code that accomplishes this rotation, explaining each method and its role in the process.
Overview
The primary function of our code is to rotate the linked list to the right by k
places. This involves three main steps:
- Calculate the size of the list and handle edge cases.
- Determine the new head of the list after rotation.
- Update the tail of the list.
Here’s a detailed explanation of the methods involved:
Method: rotate(int k)
public void rotate (int k){this.head = this.rotate(this.head, k);//udpate tail valuethis.tail = this.travelToTail();}
- Purpose: Public method to rotate the linked list by
k
places. - Implementation:
- Calls the
rotate
method (which handles the actual rotation logic) and updates thehead
of the list. - Updates the
tail
of the list by callingtravelToTail
, which finds the new tail after the rotation.
- Calls the
Method: travelToTail() #
private Node travelToTail () {Node slow = head; //it will store the mid nodeNode fast = head; //it will store the last nodewhile (fast.next != null && fast.next.next != null){slow = slow.next;fast = fast.next.next;}if(fast.next != null){while(fast.next != null){fast = fast.next;}}return fast;}
- Purpose: Helper method to find the last node (tail) of the list.
- Implementation:
- Uses two pointers,
slow
andfast
, to traverse the list.slow
moves one step at a time, whilefast
moves two steps at a time. - When
fast
reaches the end,slow
will be at the middle node (useful for other operations like finding the middle node). - If
fast.next
is not null,fast
will be moved to the end of the list. - Returns the
fast
node, which is the tail of the list.
- Uses two pointers,
Method: rotate(Node head, int k)
/* Rotate the list to the right by k places. */protected static Node rotate (Node head, int k){if(k == 0 || head == null){return head;}int size = 1;Node current = head;//travel in the list until the last nodewhile(current.next != null){size++;current = current.next;}current.next = head;k = k % size; //ensure that k is below the size of the linked list//travel until the node that need to be splitfor(int i = 0; i < size - k; i++){current = current.next;}head = current.next;current.next = null;return head;}
- Purpose: Rotates the linked list to the right by
k
places. - Implementation:
- Edge Cases: If
k
is 0 or the list is empty, the list remains unchanged. - Calculate Size: Traverse the list to determine its size.
- Form Circular List: Connect the end of the list to the head to simplify rotation.
- Find New Head: Use the value of
k
modulo the size to handle cases wherek
is larger than the list size. Traverse to find the node that will become the new tail. - Break Circular Link: Update the
head
to the new start and set the old tail’s next reference to null to finalize the rotation.
- Edge Cases: If
Time and Space Complexity
- Time Complexity: O(n), where n is the number of nodes in the linked list. The list is traversed a few times, but each traversal is linear in time.
- Space Complexity: O(1). The rotation is done in-place without requiring additional space proportional to the size of the list.
Conclusion
Rotating a linked list is a powerful technique for manipulating list data in various applications. By leveraging a circular list approach and careful pointer management, we can efficiently rotate the list with minimal overhead. This approach ensures that we maintain linear time complexity and constant space complexity, making it suitable for large lists and real-time applications.