Given the head of a linked list, rotate the list to the right by k places.
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:
[0, 500].-100 <= Node.val <= 1000 <= k <= 2 * 109The Rotate List problem asks you to rotate a singly linked list to the right by k positions. A straightforward idea is to repeatedly move the last node to the front, but this becomes inefficient for large k. A more optimal strategy relies on understanding the length of the list and using a two-pointer technique.
First, traverse the list to compute its length and identify the tail node. Since rotating by the list length results in the same list, reduce the rotations using k % length. Then locate the new tail by moving length - k - 1 steps from the head. The node after this becomes the new head. By temporarily connecting the tail to the head, you can treat the list as circular and then break the link at the correct position.
This approach efficiently performs the rotation in O(n) time with O(1) extra space.
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Length Calculation + Two Pointer Rotation | O(n) | O(1) |
Greg Hogg
This approach involves converting the linked list into a circular list and then breaking it at the correct point to achieve the required rotation.
By making the linked list a circular one, you can easily traverse k nodes from the end to set the new head and make necessary detachments.
Time Complexity: O(n) because we pass through the list twice, once to find the length and once to find the new head.
Space Complexity: O(1) since we only use a constant amount of extra space.
1#include <stdio.h>
2#include <stdlib.h>
3
4struct ListNode {
5 int val;
6 struct ListNode *next;
7};
8
9struct ListNode* rotateRight(struct ListNode* head, int k) {
10 if (!head || k == 0) return head;
11 struct ListNode *curr = head;
12 int length = 1;
13 while (curr->next) {
14 curr = curr->next;
15 length++;
16 }
17 curr->next = head; // Make it circular
18 k = k % length;
19 for (int i = 0; i < length - k; i++) {
20 curr = curr->next;
21 }
22 head = curr->next;
23 curr->next = NULL;
24 return head;
25}
26
27// Helper function to print the list
28void printList(struct ListNode *node) {
29 while (node != NULL) {
30 printf("%d ", node->val);
31 node = node->next;
32 }
33}
34
35// Example usage
36int main() {
37 struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
38 head->val = 1; head->next = (struct ListNode*)malloc(sizeof(struct ListNode));
39 head->next->val = 2; head->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));
40 head->next->next->val = 3; head->next->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));
41 head->next->next->next->val = 4; head->next->next->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));
42 head->next->next->next->next->val = 5; head->next->next->next->next->next = NULL;
43 head = rotateRight(head, 2);
44 printList(head);
45 return 0;
46}In this solution, we first determine the length of the list and then make it circular. We perform a modulus operation on k to handle cases where k is greater than the length, effectively making unnecessary additional full rotations. Finally, we iterate over the circular list to the correct point to form a valid, rotated list, detaching the circle.
In this approach, we utilize a two-pointer technique. We advance one pointer ahead by k nodes and then move another pointer from the start concurrently until the first pointer reaches the list's end. This way, the second pointer will eventually land on the node that will become the new tail.
Time Complexity: O(n) because it requires traversal for counting.
Space Complexity: O(1) as no extra space is used.
1#include <iostream>
2using namespace std;
3
4struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (!head || k == 0) return head;
ListNode* fast = head, *slow = head;
int length = 1;
while (fast->next) {
fast = fast->next;
++length;
}
fast->next = head;
k %= length;
for (int i = 0; i < length - k; i++) {
slow = slow->next;
fast = fast->next;
}
head = slow->next;
fast->next = NULL;
return head;
}
};
// Example usage
int main() {
auto *head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(3);
head->next->next->next = new ListNode(4);
head->next->next->next->next = new ListNode(5);
Solution sol;
head = sol.rotateRight(head, 2);
while (head) {
cout << head->val << " ";
head = head->next;
}
return 0;
}Watch expert explanations and walkthroughs
Practice problems asked by these companies to ace your technical interviews.
Explore More ProblemsJot down your thoughts, approach, and key learnings
If k is larger than the length of the list, rotating more than the list size results in repeated patterns. Using k % length eliminates unnecessary rotations and ensures we only perform the minimum required shifts.
Yes, linked list manipulation problems like Rotate List are common in FAANG and other top tech company interviews. They test understanding of pointers, list traversal, and edge case handling.
The optimal approach first computes the length of the linked list and reduces k using k % length. Then it finds the new tail using a pointer traversal and reconnects the list accordingly. This method rotates the list in O(n) time and O(1) space.
The problem uses a singly linked list as the main data structure. Efficient traversal and pointer manipulation are key to changing node connections without creating extra structures.
This C++ solution starts by counting the length and linking the last node to the head to form a loop. It then uses two pointers: a fast pointer that traverses k nodes firstly and a slow pointer that starts from the head. Then moving both forward will find the new head when the fast pointer completes the loop.