Rotate List

Updated on 23 June, 2025
Rotate List header image

Problem Statement

In this challenge, you are assigned a singly linked list and an integer k. Your task is to rotate the list to the right by k places. This means the last k elements of the linked list will move to the front, maintaining their order, effectively shifting the list's elements towards the tail, with wrap-around of elements to the list's head. For instance, rotating the list [1,2,3,4,5] by two positions results in [4,5,1,2,3].

Examples

Example 1

Input:

head = [1,2,3,4,5], k = 2

Output:

[4,5,1,2,3]

Example 2

Input:

head = [0,1,2], k = 4

Output:

[2,0,1]

Constraints

  • The number of nodes in the list is in the range [0, 500].
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109

Approach and Intuition

When faced with a linked list rotation problem, the intuitive approach is to reconnect the tail of the list to the head and then locate the new head and tail based on the value of k. Here’s how to systematically achieve this:

  1. Address the special cases, especially when the linked list is empty or k is zero, which means no rotation is needed.
  2. Normalize k as rotating a list of length n by n, 2n, or any multiple of n results back in the same list. This is done using k = k % n.
  3. Identify the new tail of the list, which will be at position (n - k - 1) if n is the length of the list.
  4. Make the node at position (n - k) the new head and the node at position (n - k - 1) should point to null (breaking the loop created by connecting the old tail to the head).

The challenge is simplified by understanding two key concepts:

  • A full rotation of the list by its length n results in the same list. This observation allows us to reduce computational steps dramatically when k is large (e.g., in the order of billions).
  • The essence of rotation logic lies in reconnecting the tail to the head and correctly determining the new head based on the k rotations reduced modulo. This ensures our solution works efficiently within the constraint limits.

Given the constraints like a limit of 500 nodes, this approach ensures optimal computation without running into performance bottlenecks or unnecessary complexity.

Solutions

  • C++
  • Java
  • C
  • JavaScript
  • Python
cpp
class Solution {
public:
    ListNode* rotateLinkedList(ListNode* head, int k) {
        if (!head || !(head->next)) return head;
        ListNode* lastNode = head;
        int length;
        for (length = 1; lastNode->next; length++) lastNode = lastNode->next;
        lastNode->next = head;
        ListNode* newEnd = head;
        for (int i = 0; i < length - k % length - 1; i++) newEnd = newEnd->next;
        ListNode* newHead = newEnd->next;
        newEnd->next = NULL;
        return newHead;
    }
};

This C++ solution implements a function to rotate a singly linked list by k places. Here's how the code accomplishes this:

  1. The function rotateLinkedList starts by checking if the list is empty or only contains one node, returning the head if true, as no rotation is needed.
  2. It proceeds to determine the length of the list by iterating through the list until it reaches the last node, storing the length in the variable length.
  3. The last node's next pointer is set to point back to the head, forming a circular linked list temporarily.
  4. To find the correct new end of the rotated list, the code calculates the effective rotation needed (with k % length) since rotating a list by its length results in the same list.
  5. It then iterates through the list to the new end node (length - k % length - 1 times).
  6. The new head of the list is the node right after the new end.
  7. To finalize the list rotation, the next pointer of the new end node is set to NULL, breaking the circular structure and establishing the new end.
  8. The function returns the new head, effectively rotating the list to the right by k places.

Key Points:

  • The rotation is efficiently handled by first forming a circular list and then fixing the correct start and end points.
  • Calculating k % length avoids unnecessary rotations equivalent to the entire list length or more.
  • The method ensures every node is visited only a limited number of times, resulting in a linear time complexity relative to the number of nodes.
java
class Solution {
    public ListNode rotateLinkedList(ListNode startNode, int rotations) {
        if (startNode == null) return null;
        if (startNode.next == null) return startNode;

        ListNode tailNode = startNode;
        int listLength;
        for (listLength = 1; tailNode.next != null; listLength++) tailNode = tailNode.next;
        tailNode.next = startNode;

        ListNode newTail = startNode;
        for (int i = 0; i < listLength - (rotations % listLength) - 1; i++) newTail = newTail.next;
        ListNode newHead = newTail.next;

        newTail.next = null;

        return newHead;
    }
}

The provided Java solution details a method for rotating a linked list to the right by a specified number of positions. The method, rotateLinkedList, takes two parameters: the head of the linked list (startNode) and the number of rotations (rotations). The approach involves several steps:

  1. First, handle edge cases where the linked list is empty or consists of a single node. In these scenarios, return null or the node itself, respectively.
  2. Establish the length of the list and create a circular linked list by linking the last node (tailNode) back to the startNode.
  3. Calculate the effective number of rotations needed by taking the modulus of the rotations with the list length. This accounts for scenarios where the number of rotations exceeds the length of the list.
  4. Identify the new tail of the linked list, which is positioned at listLength - (rotations % listLength) - 1 from the start, by traversing the list. The node next to this new tail becomes the new head of the rotated list.
  5. Finally, break the circular link by setting the next property of the new tail node to null.

The method returns the new head of the rotated list as the output. Through this approach, the list is efficiently rotated in place without needing additional lists or storage, optimizing both time and space complexity. This solution leverages the circular linked list concept to simplify rotation and achieve the desired configuration.

c
struct ListNode* rotateLinkedList(struct ListNode* head, int k) {
    if (head == NULL || head->next == NULL) return head;

    struct ListNode* lastElement = head;
    int len;
    for (len = 1; lastElement->next != NULL; len++) lastElement = lastElement->next;
    lastElement->next = head;

    struct ListNode* new_tail = head;
    for (int i = 0; i < len - k % len - 1; i++) new_tail = new_tail->next;
    struct ListNode* new_head = new_tail->next;

    new_tail->next = NULL;

    return new_head;
}

The provided C function rotateLinkedList rotates a singly linked list right by k places. Here's how it achieves this rotation:

  • First, check if the list is empty (i.e., head is NULL) or has only one element (i.e., head->next is NULL). If either condition is true, return the head since no rotation is needed.
  • Initialize a pointer lastElement to traverse the list and determine its length (len). Also, set lastElement->next to point to head to temporarily create a circular linked list.
  • Calculate the new tail of the list which is len - k % len - 1 steps from the head. Use a loop to move the pointer new_tail to this position.
  • Define new_head as the node immediately after new_tail (i.e., new_tail->next). This will be the new head of the rotated list.
  • Set new_tail->next to NULL to break the circular linkage, thus formally defining the end of the linear linked list.
  • Return new_head, the new start of the rotated list.

This function efficiently handles lists of any size and correctly adjusts for rotations larger than the list's length using k % len. The use of a circular linked list strategy simplifies the rotation process without needing additional data structures.

js
var rotateLinkedList = function(node, rotations) {
    if (node == null) return null;
    if (node.next == null) return node;

    let lastNode = node;
    let length;
    for (length = 1; lastNode.next != null; length++) 
        lastNode = lastNode.next;
    lastNode.next = node;

    let newLast = node;
    for (let i = 0; i < length - rotations % length - 1; i++) 
        newLast = newLast.next;
    let newHead = newLast.next;

    newLast.next = null;
    return newHead;
};

The provided solution tackles the task of rotating a singly linked list to the right by a given number of positions. It is written in JavaScript as a function rotateLinkedList that accepts two parameters: node, which is the head of the linked list, and rotations, the number of positions by which the list should be rotated.

Behavior Analysis:

  • The solution first checks if the list is empty (node == null) or contains a single element (node.next == null), in which cases it returns the list as is since no rotation is needed or possible.
  • The function calculates the linked list's length by traversing from the head node to the last node.
  • It connects the last node of the list to the head, forming a circular linked list temporarily.
  • Using the formula (length - rotations % length - 1), the new end of the rotated list is found. This calculation ensures handling rotations exceeding the length of the list.
  • It sets newLast.next to null to break the circular form and establish the new end of the list.
  • Finally, newHead, the starting node of the rotated list, is returned.

Further Explanation:

  • By connecting the head to the last node, the list manipulation becomes easier as it allows the rotation to be handled without explicitly handling node relinking for each rotation.
  • The modulo operation with the list's length (rotations % length) ensures that the number of rotations do not exceed the list's length, preventing unnecessary processing.
  • This code guarantees an O(n) time complexity since it involves a complete traversal of the list at least twice, making it efficient for reasonable list sizes and rotation values.
python
class Solution:
    def rotateList(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or not head.next:
            return head
        
        # Create a closed loop
        last_node = head
        length = 1
        while last_node.next:
            last_node = last_node.next
            length += 1
        last_node.next = head
        
        # Find the point to break the loop
        steps_to_new_head = length - k % length
        new_end = head
        for _ in range(steps_to_new_head - 1):
            new_end = new_end.next
        starting_head = new_end.next
        
        # Break the loop
        new_end.next = None
        
        return starting_head

The provided Python solution is designed to rotate a linked list by k positions to the right. The process involves several key operations:

  • Initially, the function checks if the head is None or if the list contains only one node. In either case, it returns the head as no rotation is needed.

  • The algorithm then creates a closed loop from the list. This is achieved by traversing to the last node of the list, counting the nodes along the way to ascertain the length, and then connecting the last node back to the head.

  • Once the list has been converted into a circular linked list, the rotation is handled by computing the effective number of rotations needed (k % length). This calculation is necessary because rotating a list of length L by L times results in the same list, hence rotations beyond the length of the list are redundant.

  • Determining the new head involves moving to the length - k % length node in the list. This traversal is performed starting from the current head.

  • After identifying the new end of the rotated list (new_end), the node next to new_end is set as the new head, and the circular linkage is broken by setting new_end.next to None.

  • Finally, the function returns the new head of the rotated list, effectively completing the rotation.

This solution makes use of a clever technique to minimize the list traversals and is efficient in terms of time and space with regard to handling list rotations.

Comments

No comments yet.