Rotate List
Problem Statement
Section titled “Problem Statement”Given the head of a linked list, rotate the list to the right by k places.
Rotating a list to the right by k places means taking the last k nodes and moving them to the front of the list, preserving their relative order.
Examples
Section titled “Examples”| Input | k | Output | Explanation |
|---|---|---|---|
1 → 2 → 3 → 4 → 5 | 2 | 4 → 5 → 1 → 2 → 3 | Move the last 2 nodes to the front |
0 → 1 → 2 | 4 | 2 → 0 → 1 | k % length = 4 % 3 = 1, rotate by 1 |
1 | 1 | 1 | Single node; rotation has no effect |
1 → 2 | 2 | 1 → 2 | Full rotation by list length; no change |
Constraints
Section titled “Constraints”- The number of nodes in the list is in the range
[0, 100]. 0 <= Node.val <= 1000 <= k <= 2 * 10^9
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Passes | Best When |
|---|---|---|---|---|
| Break Point | O(n) | O(1) | 2 | Easier to understand the concept; clear two-phase algorithm |
| Circular | O(n) | O(1) | 1 | Want a more elegant single-pass-like approach; showing pattern mastery |
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick Break Point if you are learning linked list manipulation for the first time.
- Pick Circular if you want to see an elegant alternative using the cyclic nature of the problem.
Approach 1: Break Point
Section titled “Approach 1: Break Point”Find the node at position (length - k - 1) and break the list there. The new head is the node that follows this break point. Reconnect the tail of the rotated portion to the original head.
The key insight is understanding that after a right rotation by k, the node that was at position length - k becomes the new head.
Step-by-step Example
Section titled “Step-by-step Example”Input: 1 → 2 → 3 → 4 → 5, k = 2
Step 1: Find length = 5
Step 2: Normalize k = 2 (already less than 5)
Step 3: Find break point at position 5 - 2 - 1 = 2 (the node with value 3)
Step 4: Break the list:
- Separate:
1 → 2 → 3(break here) and4 → 5 - Set
3.next = null - Connect the tail of
4 → 5(which is 5) back to 1 - Result:
4 → 5 → 1 → 2 → 3
Another case: 0 → 1 → 2, k = 4
Step 1: Find length = 3
Step 2: Normalize k = 4 % 3 = 1
Step 3: Find break point at position 3 - 1 - 1 = 1 (the node with value 1)
Step 4: Break and reconnect:
0 → 1and22.nextpoints to0- Result:
2 → 0 → 1
Pseudocode
Section titled “Pseudocode”function rotateListBreakPoint(head, k): if head is null or head.next is null or k == 0: return head
// Step 1: Find length length = 0 current = head while current != null: length++ current = current.next
// Step 2: Normalize k k = k % length if k == 0: return head
// Step 3: Find break point current = head for i from 0 to length - k - 2: current = current.next
// Step 4: Break and reconnect newHead = current.next current.next = null tail = newHead while tail.next != null: tail = tail.next tail.next = head
return newHeadSolution Code
Section titled “Solution Code”from typing import Optional
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
def rotate_list_break_point(head: Optional[ListNode], k: int) -> Optional[ListNode]: """ Rotate a linked list to the right by k positions using the break point approach.
Approach: 1. Calculate the effective rotation: k = k % length 2. Find the break point: the node at position (length - k - 1) 3. Perform rotation by breaking the list at the break point
Time: O(n) - single pass to find length, single pass to find break point Space: O(1) - only using pointers """ if not head or not head.next or k == 0: return head
# Step 1: Find the length of the list length = 0 current = head while current: length += 1 current = current.next
# Step 2: Normalize k (handle cases where k > length) k = k % length if k == 0: return head
# Step 3: Find the break point (node before rotation point) # We need to find the (length - k - 1)th node current = head for i in range(length - k - 1): current = current.next
# Step 4: Perform rotation # The new head is current.next new_head = current.next current.next = None # Find the tail of the new list and connect it back to the old head tail = new_head while tail.next: tail = tail.next tail.next = head
return new_head
# Helper function to create a linked list from a listdef create_linked_list(values): if not values: return None head = ListNode(values[0]) current = head for val in values[1:]: current.next = ListNode(val) current = current.next return head
# Helper function to convert linked list to list for easy printingdef linked_list_to_list(head): result = [] current = head while current: result.append(current.val) current = current.next return result
# Test casesif __name__ == "__main__": # Test 1: [1, 2, 3, 4, 5], k=2 head1 = create_linked_list([1, 2, 3, 4, 5]) result1 = rotate_list_break_point(head1, 2) print(linked_list_to_list(result1)) # [4, 5, 1, 2, 3]
# Test 2: [0, 1, 2], k=4 head2 = create_linked_list([0, 1, 2]) result2 = rotate_list_break_point(head2, 4) print(linked_list_to_list(result2)) # [2, 0, 1]
# Test 3: [1], k=1 head3 = create_linked_list([1]) result3 = rotate_list_break_point(head3, 1) print(linked_list_to_list(result3)) # [1]
# Test 4: [1, 2], k=2 head4 = create_linked_list([1, 2]) result4 = rotate_list_break_point(head4, 2) print(linked_list_to_list(result4)) # [1, 2]
# Test 5: [1, 2, 3, 4, 5], k=0 head5 = create_linked_list([1, 2, 3, 4, 5]) result5 = rotate_list_break_point(head5, 0) print(linked_list_to_list(result5)) # [1, 2, 3, 4, 5]#include <iostream>#include <vector>using namespace std;
struct ListNode { int val; ListNode *next; ListNode(int x = 0, ListNode *n = nullptr) : val(x), next(n) {}};
ListNode *rotate_list_break_point(ListNode *head, int k) { /** * Rotate a linked list to the right by k positions using the break point approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Find the break point: the node at position (length - k - 1) * 3. Perform rotation by breaking the list at the break point * * Time: O(n) - single pass to find length, single pass to find break point * Space: O(1) - only using pointers */
if (!head || !head->next || k == 0) { return head; }
// Step 1: Find the length of the list int length = 0; ListNode *current = head; while (current) { length++; current = current->next; }
// Step 2: Normalize k (handle cases where k > length) k = k % length; if (k == 0) { return head; }
// Step 3: Find the break point (node before rotation point) // We need to find the (length - k - 1)th node current = head; for (int i = 0; i < length - k - 1; i++) { current = current->next; }
// Step 4: Perform rotation // The new head is current->next ListNode *new_head = current->next; current->next = nullptr;
// Find the tail of the new list and connect it back to the old head ListNode *tail = new_head; while (tail->next) { tail = tail->next; } tail->next = head;
return new_head;}
// Helper function to create a linked list from a vectorListNode *create_linked_list(vector<int> &values) { if (values.empty()) return nullptr; ListNode *head = new ListNode(values[0]); ListNode *current = head; for (int i = 1; i < values.size(); i++) { current->next = new ListNode(values[i]); current = current->next; } return head;}
// Helper function to convert linked list to vector for easy printingvector<int> linked_list_to_vector(ListNode *head) { vector<int> result; ListNode *current = head; while (current) { result.push_back(current->val); current = current->next; } return result;}
// Helper function to print a vectorvoid print_vector(const vector<int> &v) { cout << "["; for (int i = 0; i < v.size(); i++) { cout << v[i]; if (i < v.size() - 1) cout << ", "; } cout << "]" << endl;}
// Test casesint main() { // Test 1: [1, 2, 3, 4, 5], k=2 vector<int> vals1 = {1, 2, 3, 4, 5}; ListNode *head1 = create_linked_list(vals1); ListNode *result1 = rotate_list_break_point(head1, 2); print_vector(linked_list_to_vector(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 vector<int> vals2 = {0, 1, 2}; ListNode *head2 = create_linked_list(vals2); ListNode *result2 = rotate_list_break_point(head2, 4); print_vector(linked_list_to_vector(result2)); // [2, 0, 1]
// Test 3: [1], k=1 vector<int> vals3 = {1}; ListNode *head3 = create_linked_list(vals3); ListNode *result3 = rotate_list_break_point(head3, 1); print_vector(linked_list_to_vector(result3)); // [1]
// Test 4: [1, 2], k=2 vector<int> vals4 = {1, 2}; ListNode *head4 = create_linked_list(vals4); ListNode *result4 = rotate_list_break_point(head4, 2); print_vector(linked_list_to_vector(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 vector<int> vals5 = {1, 2, 3, 4, 5}; ListNode *head5 = create_linked_list(vals5); ListNode *result5 = rotate_list_break_point(head5, 0); print_vector(linked_list_to_vector(result5)); // [1, 2, 3, 4, 5]
return 0;}import java.util.ArrayList;import java.util.List;
class ListNode { int val; ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }}
class RotateListBreakPoint { /** * Rotate a linked list to the right by k positions using the break point approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Find the break point: the node at position (length - k - 1) * 3. Perform rotation by breaking the list at the break point * * Time: O(n) - single pass to find length, single pass to find break point * Space: O(1) - only using pointers */ public static ListNode rotateListBreakPoint(ListNode head, int k) { if (head == null || head.next == null || k == 0) { return head; }
// Step 1: Find the length of the list int length = 0; ListNode current = head; while (current != null) { length++; current = current.next; }
// Step 2: Normalize k (handle cases where k > length) k = k % length; if (k == 0) { return head; }
// Step 3: Find the break point (node before rotation point) // We need to find the (length - k - 1)th node current = head; for (int i = 0; i < length - k - 1; i++) { current = current.next; }
// Step 4: Perform rotation // The new head is current.next ListNode newHead = current.next; current.next = null;
// Find the tail of the new list and connect it back to the old head ListNode tail = newHead; while (tail.next != null) { tail = tail.next; } tail.next = head;
return newHead; }
// Helper function to create a linked list from an array public static ListNode createLinkedList(int[] values) { if (values.length == 0) return null; ListNode head = new ListNode(values[0]); ListNode current = head; for (int i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head; }
// Helper function to convert linked list to list for easy printing public static List<Integer> linkedListToList(ListNode head) { List<Integer> result = new ArrayList<>(); ListNode current = head; while (current != null) { result.add(current.val); current = current.next; } return result; }
// Test cases public static void main(String[] args) { // Test 1: [1, 2, 3, 4, 5], k=2 ListNode head1 = createLinkedList(new int[]{1, 2, 3, 4, 5}); ListNode result1 = rotateListBreakPoint(head1, 2); System.out.println(linkedListToList(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 ListNode head2 = createLinkedList(new int[]{0, 1, 2}); ListNode result2 = rotateListBreakPoint(head2, 4); System.out.println(linkedListToList(result2)); // [2, 0, 1]
// Test 3: [1], k=1 ListNode head3 = createLinkedList(new int[]{1}); ListNode result3 = rotateListBreakPoint(head3, 1); System.out.println(linkedListToList(result3)); // [1]
// Test 4: [1, 2], k=2 ListNode head4 = createLinkedList(new int[]{1, 2}); ListNode result4 = rotateListBreakPoint(head4, 2); System.out.println(linkedListToList(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 ListNode head5 = createLinkedList(new int[]{1, 2, 3, 4, 5}); ListNode result5 = rotateListBreakPoint(head5, 0); System.out.println(linkedListToList(result5)); // [1, 2, 3, 4, 5] }}class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; }}
/** * Rotate a linked list to the right by k positions using the break point approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Find the break point: the node at position (length - k - 1) * 3. Perform rotation by breaking the list at the break point * * Time: O(n) - single pass to find length, single pass to find break point * Space: O(1) - only using pointers */function rotateListBreakPoint(head, k) { if (!head || !head.next || k === 0) { return head; }
// Step 1: Find the length of the list let length = 0; let current = head; while (current) { length++; current = current.next; }
// Step 2: Normalize k (handle cases where k > length) k = k % length; if (k === 0) { return head; }
// Step 3: Find the break point (node before rotation point) // We need to find the (length - k - 1)th node current = head; for (let i = 0; i < length - k - 1; i++) { current = current.next; }
// Step 4: Perform rotation // The new head is current.next const newHead = current.next; current.next = null;
// Find the tail of the new list and connect it back to the old head let tail = newHead; while (tail.next) { tail = tail.next; } tail.next = head;
return newHead;}
// Helper function to create a linked list from an arrayfunction createLinkedList(values) { if (values.length === 0) return null; const head = new ListNode(values[0]); let current = head; for (let i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head;}
// Helper function to convert linked list to array for easy printingfunction linkedListToArray(head) { const result = []; let current = head; while (current) { result.push(current.val); current = current.next; } return result;}
// Test casesif (require.main === module) { // Test 1: [1, 2, 3, 4, 5], k=2 let head1 = createLinkedList([1, 2, 3, 4, 5]); let result1 = rotateListBreakPoint(head1, 2); console.log(linkedListToArray(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 let head2 = createLinkedList([0, 1, 2]); let result2 = rotateListBreakPoint(head2, 4); console.log(linkedListToArray(result2)); // [2, 0, 1]
// Test 3: [1], k=1 let head3 = createLinkedList([1]); let result3 = rotateListBreakPoint(head3, 1); console.log(linkedListToArray(result3)); // [1]
// Test 4: [1, 2], k=2 let head4 = createLinkedList([1, 2]); let result4 = rotateListBreakPoint(head4, 2); console.log(linkedListToArray(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 let head5 = createLinkedList([1, 2, 3, 4, 5]); let result5 = rotateListBreakPoint(head5, 0); console.log(linkedListToArray(result5)); // [1, 2, 3, 4, 5]}
module.exports = { rotateListBreakPoint, ListNode, createLinkedList, linkedListToArray };use std::cell::RefCell;use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]pub struct ListNode { pub val: i32, pub next: Option<Rc<RefCell<ListNode>>>,}
impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } }}
/// Rotate a linked list to the right by k positions using the break point approach.////// Approach:/// 1. Calculate the effective rotation: k = k % length/// 2. Find the break point: the node at position (length - k - 1)/// 3. Perform rotation by breaking the list at the break point////// Time: O(n) - single pass to find length, single pass to find break point/// Space: O(1) - only using pointerspub fn rotate_list_break_point(head: Option<Rc<RefCell<ListNode>>>, k: i32) -> Option<Rc<RefCell<ListNode>>> { let head = match head { Some(h) => h, None => return None, };
// Check if next is None (single node or empty) { let head_ref = head.borrow(); if head_ref.next.is_none() || k == 0 { return Some(head.clone()); } }
// Step 1: Find the length of the list let mut length = 0; let mut current = Some(head.clone()); while let Some(node) = current { length += 1; let next = node.borrow_mut().next.take(); current = next; }
// Step 2: Normalize k let k = k % length; if k == 0 { return Some(head); }
// Step 3: Find the break point let mut current = Some(head.clone()); for _ in 0..length - k - 1 { let node = current.unwrap(); let next = node.borrow_mut().next.take(); current = next; }
// Step 4: Perform rotation let break_node = current.unwrap(); let new_head = break_node.borrow_mut().next.take();
if let Some(new_head_node) = new_head { // Find tail and connect to old head let mut tail = Some(new_head_node.clone()); while let Some(node) = tail { if node.borrow().next.is_none() { node.borrow_mut().next = Some(head); return Some(new_head_node); } let next = node.borrow_mut().next.take(); tail = next; } }
Some(head)}
// Helper function to create a linked list from a vectorpub fn create_linked_list(values: Vec<i32>) -> Option<Rc<RefCell<ListNode>>> { if values.is_empty() { return None; }
let head = Rc::new(RefCell::new(ListNode::new(values[0]))); let mut current = head.clone();
for val in values.into_iter().skip(1) { let new_node = Rc::new(RefCell::new(ListNode::new(val))); current.borrow_mut().next = Some(new_node.clone()); current = new_node; }
Some(head)}
// Helper function to convert linked list to vector for easy printingpub fn linked_list_to_vec(head: Option<Rc<RefCell<ListNode>>>) -> Vec<i32> { let mut result = vec![]; let mut current = head;
while let Some(node) = current { result.push(node.borrow().val); let next = node.borrow_mut().next.take(); current = next; }
result}
#[cfg(test)]mod tests { use super::*;
#[test] fn test_rotate_list_break_point() { // Test 1: [1, 2, 3, 4, 5], k=2 let head1 = create_linked_list(vec![1, 2, 3, 4, 5]); let result1 = rotate_list_break_point(head1, 2); assert_eq!(linked_list_to_vec(result1), vec![4, 5, 1, 2, 3]);
// Test 2: [0, 1, 2], k=4 let head2 = create_linked_list(vec![0, 1, 2]); let result2 = rotate_list_break_point(head2, 4); assert_eq!(linked_list_to_vec(result2), vec![2, 0, 1]);
// Test 3: [1], k=1 let head3 = create_linked_list(vec![1]); let result3 = rotate_list_break_point(head3, 1); assert_eq!(linked_list_to_vec(result3), vec![1]);
// Test 4: [1, 2], k=2 let head4 = create_linked_list(vec![1, 2]); let result4 = rotate_list_break_point(head4, 2); assert_eq!(linked_list_to_vec(result4), vec![1, 2]);
// Test 5: [1, 2, 3, 4, 5], k=0 let head5 = create_linked_list(vec![1, 2, 3, 4, 5]); let result5 = rotate_list_break_point(head5, 0); assert_eq!(linked_list_to_vec(result5), vec![1, 2, 3, 4, 5]); }}package main
import "fmt"
type ListNode struct { Val int Next *ListNode}
// RotateListBreakPoint rotates a linked list to the right by k positions using the break point approach.//// Approach:// 1. Calculate the effective rotation: k = k % length// 2. Find the break point: the node at position (length - k - 1)// 3. Perform rotation by breaking the list at the break point//// Time: O(n) - single pass to find length, single pass to find break point// Space: O(1) - only using pointersfunc RotateListBreakPoint(head *ListNode, k int) *ListNode { if head == nil || head.Next == nil || k == 0 { return head }
// Step 1: Find the length of the list length := 0 current := head for current != nil { length++ current = current.Next }
// Step 2: Normalize k (handle cases where k > length) k = k % length if k == 0 { return head }
// Step 3: Find the break point (node before rotation point) // We need to find the (length - k - 1)th node current = head for i := 0; i < length-k-1; i++ { current = current.Next }
// Step 4: Perform rotation // The new head is current.Next newHead := current.Next current.Next = nil
// Find the tail of the new list and connect it back to the old head tail := newHead for tail.Next != nil { tail = tail.Next } tail.Next = head
return newHead}
// Helper function to create a linked list from a slicefunc CreateLinkedList(values []int) *ListNode { if len(values) == 0 { return nil } head := &ListNode{Val: values[0]} current := head for i := 1; i < len(values); i++ { current.Next = &ListNode{Val: values[i]} current = current.Next } return head}
// Helper function to convert linked list to slice for easy printingfunc LinkedListToSlice(head *ListNode) []int { var result []int current := head for current != nil { result = append(result, current.Val) current = current.Next } return result}
// Test casesfunc main() { // Test 1: [1, 2, 3, 4, 5], k=2 head1 := CreateLinkedList([]int{1, 2, 3, 4, 5}) result1 := RotateListBreakPoint(head1, 2) fmt.Println(LinkedListToSlice(result1)) // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 head2 := CreateLinkedList([]int{0, 1, 2}) result2 := RotateListBreakPoint(head2, 4) fmt.Println(LinkedListToSlice(result2)) // [2, 0, 1]
// Test 3: [1], k=1 head3 := CreateLinkedList([]int{1}) result3 := RotateListBreakPoint(head3, 1) fmt.Println(LinkedListToSlice(result3)) // [1]
// Test 4: [1, 2], k=2 head4 := CreateLinkedList([]int{1, 2}) result4 := RotateListBreakPoint(head4, 2) fmt.Println(LinkedListToSlice(result4)) // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 head5 := CreateLinkedList([]int{1, 2, 3, 4, 5}) result5 := RotateListBreakPoint(head5, 0) fmt.Println(LinkedListToSlice(result5)) // [1, 2, 3, 4, 5]}Approach 2: Circular
Section titled “Approach 2: Circular”Create a circular list by connecting the tail back to the head, then locate the new head at position (length - k) and break the circle there. This approach elegantly leverages the cyclic nature of rotation.
Step-by-step Example
Section titled “Step-by-step Example”Input: 1 → 2 → 3 → 4 → 5, k = 2
Step 1: Find length = 5, identify tail (node 5)
Step 2: Normalize k = 2
Step 3: Create circular list: 5.next = 1 → 1 → 2 → 3 → 4 → 5 → 1 → 2 → 3 → ...
Step 4: Walk length - k = 5 - 2 = 3 steps from head (starting at position 0):
- Step 0: at node 1
- Step 1: at node 2
- Step 2: at node 3
Step 5: Break after node 3:
new_head = 3.next = 43.next = null- Result:
4 → 5 → 1 → 2 → 3
Another case: 0 → 1 → 2, k = 4
Step 1: Find length = 3, tail = node 2
Step 2: Normalize k = 1
Step 3: Create circular list: 2.next = 0
Step 4: Walk 3 - 1 = 2 steps from head:
- Step 0: at node 0
- Step 1: at node 1
Step 5: Break after node 1:
new_head = 1.next = 21.next = null- Result:
2 → 0 → 1
Pseudocode
Section titled “Pseudocode”function rotateListCircular(head, k): if head is null or head.next is null or k == 0: return head
// Step 1: Find length and tail length = 0 tail = head while tail.next != null: length++ tail = tail.next length++
// Step 2: Normalize k k = k % length if k == 0: return head
// Step 3: Create circular list tail.next = head
// Step 4: Find new head position stepsToWalk = length - k current = head for i from 0 to stepsToWalk - 2: current = current.next
// Step 5: Break the circle newHead = current.next current.next = null
return newHeadSolution Code
Section titled “Solution Code”from typing import Optional
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
def rotate_list_circular(head: Optional[ListNode], k: int) -> Optional[ListNode]: """ Rotate a linked list to the right by k positions using the circular approach.
Approach: 1. Calculate the effective rotation: k = k % length 2. Create a circular list by connecting the tail to the head 3. Find the new head position: walk (length - k) steps from the original head 4. Break the circle at the appropriate point
Time: O(n) - single pass to find length and establish circle, walk (length - k) steps Space: O(1) - only using pointers """ if not head or not head.next or k == 0: return head
# Step 1: Find the length of the list and the tail length = 0 tail = head while tail.next: length += 1 tail = tail.next length += 1 # Add 1 for the tail node itself
# Step 2: Normalize k k = k % length if k == 0: return head
# Step 3: Create a circular list tail.next = head
# Step 4: Find the new head position # After rotation by k, the new head is at position (length - k) # We need to walk (length - k) steps from the original head steps_to_walk = length - k current = head for i in range(steps_to_walk - 1): current = current.next
# Step 5: Break the circle new_head = current.next current.next = None
return new_head
# Helper function to create a linked list from a listdef create_linked_list(values): if not values: return None head = ListNode(values[0]) current = head for val in values[1:]: current.next = ListNode(val) current = current.next return head
# Helper function to convert linked list to list for easy printingdef linked_list_to_list(head): result = [] current = head while current: result.append(current.val) current = current.next return result
# Test casesif __name__ == "__main__": # Test 1: [1, 2, 3, 4, 5], k=2 head1 = create_linked_list([1, 2, 3, 4, 5]) result1 = rotate_list_circular(head1, 2) print(linked_list_to_list(result1)) # [4, 5, 1, 2, 3]
# Test 2: [0, 1, 2], k=4 head2 = create_linked_list([0, 1, 2]) result2 = rotate_list_circular(head2, 4) print(linked_list_to_list(result2)) # [2, 0, 1]
# Test 3: [1], k=1 head3 = create_linked_list([1]) result3 = rotate_list_circular(head3, 1) print(linked_list_to_list(result3)) # [1]
# Test 4: [1, 2], k=2 head4 = create_linked_list([1, 2]) result4 = rotate_list_circular(head4, 2) print(linked_list_to_list(result4)) # [1, 2]
# Test 5: [1, 2, 3, 4, 5], k=0 head5 = create_linked_list([1, 2, 3, 4, 5]) result5 = rotate_list_circular(head5, 0) print(linked_list_to_list(result5)) # [1, 2, 3, 4, 5]#include <iostream>#include <vector>using namespace std;
struct ListNode { int val; ListNode *next; ListNode(int x = 0, ListNode *n = nullptr) : val(x), next(n) {}};
ListNode *rotate_list_circular(ListNode *head, int k) { /** * Rotate a linked list to the right by k positions using the circular approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Create a circular list by connecting the tail to the head * 3. Find the new head position: walk (length - k) steps from the original head * 4. Break the circle at the appropriate point * * Time: O(n) - single pass to find length and establish circle, walk (length - k) steps * Space: O(1) - only using pointers */
if (!head || !head->next || k == 0) { return head; }
// Step 1: Find the length of the list and the tail int length = 0; ListNode *tail = head; while (tail->next) { length++; tail = tail->next; } length++; // Add 1 for the tail node itself
// Step 2: Normalize k k = k % length; if (k == 0) { return head; }
// Step 3: Create a circular list tail->next = head;
// Step 4: Find the new head position // After rotation by k, the new head is at position (length - k) // We need to walk (length - k) steps from the original head int steps_to_walk = length - k; ListNode *current = head; for (int i = 0; i < steps_to_walk - 1; i++) { current = current->next; }
// Step 5: Break the circle ListNode *new_head = current->next; current->next = nullptr;
return new_head;}
// Helper function to create a linked list from a vectorListNode *create_linked_list(vector<int> &values) { if (values.empty()) return nullptr; ListNode *head = new ListNode(values[0]); ListNode *current = head; for (int i = 1; i < values.size(); i++) { current->next = new ListNode(values[i]); current = current->next; } return head;}
// Helper function to convert linked list to vector for easy printingvector<int> linked_list_to_vector(ListNode *head) { vector<int> result; ListNode *current = head; while (current) { result.push_back(current->val); current = current->next; } return result;}
// Helper function to print a vectorvoid print_vector(const vector<int> &v) { cout << "["; for (int i = 0; i < v.size(); i++) { cout << v[i]; if (i < v.size() - 1) cout << ", "; } cout << "]" << endl;}
// Test casesint main() { // Test 1: [1, 2, 3, 4, 5], k=2 vector<int> vals1 = {1, 2, 3, 4, 5}; ListNode *head1 = create_linked_list(vals1); ListNode *result1 = rotate_list_circular(head1, 2); print_vector(linked_list_to_vector(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 vector<int> vals2 = {0, 1, 2}; ListNode *head2 = create_linked_list(vals2); ListNode *result2 = rotate_list_circular(head2, 4); print_vector(linked_list_to_vector(result2)); // [2, 0, 1]
// Test 3: [1], k=1 vector<int> vals3 = {1}; ListNode *head3 = create_linked_list(vals3); ListNode *result3 = rotate_list_circular(head3, 1); print_vector(linked_list_to_vector(result3)); // [1]
// Test 4: [1, 2], k=2 vector<int> vals4 = {1, 2}; ListNode *head4 = create_linked_list(vals4); ListNode *result4 = rotate_list_circular(head4, 2); print_vector(linked_list_to_vector(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 vector<int> vals5 = {1, 2, 3, 4, 5}; ListNode *head5 = create_linked_list(vals5); ListNode *result5 = rotate_list_circular(head5, 0); print_vector(linked_list_to_vector(result5)); // [1, 2, 3, 4, 5]
return 0;}import java.util.ArrayList;import java.util.List;
class ListNode { int val; ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }}
class RotateListCircular { /** * Rotate a linked list to the right by k positions using the circular approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Create a circular list by connecting the tail to the head * 3. Find the new head position: walk (length - k) steps from the original head * 4. Break the circle at the appropriate point * * Time: O(n) - single pass to find length and establish circle, walk (length - k) steps * Space: O(1) - only using pointers */ public static ListNode rotateListCircular(ListNode head, int k) { if (head == null || head.next == null || k == 0) { return head; }
// Step 1: Find the length of the list and the tail int length = 0; ListNode tail = head; while (tail.next != null) { length++; tail = tail.next; } length++; // Add 1 for the tail node itself
// Step 2: Normalize k k = k % length; if (k == 0) { return head; }
// Step 3: Create a circular list tail.next = head;
// Step 4: Find the new head position // After rotation by k, the new head is at position (length - k) // We need to walk (length - k) steps from the original head int stepsToWalk = length - k; ListNode current = head; for (int i = 0; i < stepsToWalk - 1; i++) { current = current.next; }
// Step 5: Break the circle ListNode newHead = current.next; current.next = null;
return newHead; }
// Helper function to create a linked list from an array public static ListNode createLinkedList(int[] values) { if (values.length == 0) return null; ListNode head = new ListNode(values[0]); ListNode current = head; for (int i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head; }
// Helper function to convert linked list to list for easy printing public static List<Integer> linkedListToList(ListNode head) { List<Integer> result = new ArrayList<>(); ListNode current = head; while (current != null) { result.add(current.val); current = current.next; } return result; }
// Test cases public static void main(String[] args) { // Test 1: [1, 2, 3, 4, 5], k=2 ListNode head1 = createLinkedList(new int[]{1, 2, 3, 4, 5}); ListNode result1 = rotateListCircular(head1, 2); System.out.println(linkedListToList(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 ListNode head2 = createLinkedList(new int[]{0, 1, 2}); ListNode result2 = rotateListCircular(head2, 4); System.out.println(linkedListToList(result2)); // [2, 0, 1]
// Test 3: [1], k=1 ListNode head3 = createLinkedList(new int[]{1}); ListNode result3 = rotateListCircular(head3, 1); System.out.println(linkedListToList(result3)); // [1]
// Test 4: [1, 2], k=2 ListNode head4 = createLinkedList(new int[]{1, 2}); ListNode result4 = rotateListCircular(head4, 2); System.out.println(linkedListToList(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 ListNode head5 = createLinkedList(new int[]{1, 2, 3, 4, 5}); ListNode result5 = rotateListCircular(head5, 0); System.out.println(linkedListToList(result5)); // [1, 2, 3, 4, 5] }}class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; }}
/** * Rotate a linked list to the right by k positions using the circular approach. * * Approach: * 1. Calculate the effective rotation: k = k % length * 2. Create a circular list by connecting the tail to the head * 3. Find the new head position: walk (length - k) steps from the original head * 4. Break the circle at the appropriate point * * Time: O(n) - single pass to find length and establish circle, walk (length - k) steps * Space: O(1) - only using pointers */function rotateListCircular(head, k) { if (!head || !head.next || k === 0) { return head; }
// Step 1: Find the length of the list and the tail let length = 0; let tail = head; while (tail.next) { length++; tail = tail.next; } length++; // Add 1 for the tail node itself
// Step 2: Normalize k k = k % length; if (k === 0) { return head; }
// Step 3: Create a circular list tail.next = head;
// Step 4: Find the new head position // After rotation by k, the new head is at position (length - k) // We need to walk (length - k) steps from the original head const stepsToWalk = length - k; let current = head; for (let i = 0; i < stepsToWalk - 1; i++) { current = current.next; }
// Step 5: Break the circle const newHead = current.next; current.next = null;
return newHead;}
// Helper function to create a linked list from an arrayfunction createLinkedList(values) { if (values.length === 0) return null; const head = new ListNode(values[0]); let current = head; for (let i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head;}
// Helper function to convert linked list to array for easy printingfunction linkedListToArray(head) { const result = []; let current = head; while (current) { result.push(current.val); current = current.next; } return result;}
// Test casesif (require.main === module) { // Test 1: [1, 2, 3, 4, 5], k=2 let head1 = createLinkedList([1, 2, 3, 4, 5]); let result1 = rotateListCircular(head1, 2); console.log(linkedListToArray(result1)); // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 let head2 = createLinkedList([0, 1, 2]); let result2 = rotateListCircular(head2, 4); console.log(linkedListToArray(result2)); // [2, 0, 1]
// Test 3: [1], k=1 let head3 = createLinkedList([1]); let result3 = rotateListCircular(head3, 1); console.log(linkedListToArray(result3)); // [1]
// Test 4: [1, 2], k=2 let head4 = createLinkedList([1, 2]); let result4 = rotateListCircular(head4, 2); console.log(linkedListToArray(result4)); // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 let head5 = createLinkedList([1, 2, 3, 4, 5]); let result5 = rotateListCircular(head5, 0); console.log(linkedListToArray(result5)); // [1, 2, 3, 4, 5]}
module.exports = { rotateListCircular, ListNode, createLinkedList, linkedListToArray };use std::cell::RefCell;use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]pub struct ListNode { pub val: i32, pub next: Option<Rc<RefCell<ListNode>>>,}
impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } }}
/// Rotate a linked list to the right by k positions using the circular approach.////// Approach:/// 1. Calculate the effective rotation: k = k % length/// 2. Create a circular list by connecting the tail to the head/// 3. Find the new head position: walk (length - k) steps from the original head/// 4. Break the circle at the appropriate point////// Time: O(n) - single pass to find length and establish circle, walk (length - k) steps/// Space: O(1) - only using pointerspub fn rotate_list_circular(head: Option<Rc<RefCell<ListNode>>>, k: i32) -> Option<Rc<RefCell<ListNode>>> { let head = match head { Some(h) => h, None => return None, };
// Check if next is None (single node or empty) { let head_ref = head.borrow(); if head_ref.next.is_none() || k == 0 { return Some(head.clone()); } }
// Step 1: Find the length of the list and the tail let mut length = 1; let mut current = Some(head.clone()); let mut tail_node = None;
while let Some(node) = current { let next = node.borrow_mut().next.take(); if next.is_none() { tail_node = Some(node.clone()); } else { length += 1; } current = next; }
// Step 2: Normalize k let k = k % length; if k == 0 { return Some(head); }
// Step 3: Create a circular list if let Some(tail) = tail_node { tail.borrow_mut().next = Some(head.clone());
// Step 4: Find the new head position let steps_to_walk = length - k; let mut current = Some(head.clone()); for _ in 0..steps_to_walk - 1 { let node = current.unwrap(); let next = node.borrow_mut().next.take(); current = next; }
// Step 5: Break the circle let break_node = current.unwrap(); let new_head = break_node.borrow_mut().next.take();
return new_head; }
Some(head)}
// Helper function to create a linked list from a vectorpub fn create_linked_list(values: Vec<i32>) -> Option<Rc<RefCell<ListNode>>> { if values.is_empty() { return None; }
let head = Rc::new(RefCell::new(ListNode::new(values[0]))); let mut current = head.clone();
for val in values.into_iter().skip(1) { let new_node = Rc::new(RefCell::new(ListNode::new(val))); current.borrow_mut().next = Some(new_node.clone()); current = new_node; }
Some(head)}
// Helper function to convert linked list to vector for easy printingpub fn linked_list_to_vec(head: Option<Rc<RefCell<ListNode>>>) -> Vec<i32> { let mut result = vec![]; let mut current = head;
while let Some(node) = current { result.push(node.borrow().val); let next = node.borrow_mut().next.take(); current = next; }
result}
#[cfg(test)]mod tests { use super::*;
#[test] fn test_rotate_list_circular() { // Test 1: [1, 2, 3, 4, 5], k=2 let head1 = create_linked_list(vec![1, 2, 3, 4, 5]); let result1 = rotate_list_circular(head1, 2); assert_eq!(linked_list_to_vec(result1), vec![4, 5, 1, 2, 3]);
// Test 2: [0, 1, 2], k=4 let head2 = create_linked_list(vec![0, 1, 2]); let result2 = rotate_list_circular(head2, 4); assert_eq!(linked_list_to_vec(result2), vec![2, 0, 1]);
// Test 3: [1], k=1 let head3 = create_linked_list(vec![1]); let result3 = rotate_list_circular(head3, 1); assert_eq!(linked_list_to_vec(result3), vec![1]);
// Test 4: [1, 2], k=2 let head4 = create_linked_list(vec![1, 2]); let result4 = rotate_list_circular(head4, 2); assert_eq!(linked_list_to_vec(result4), vec![1, 2]);
// Test 5: [1, 2, 3, 4, 5], k=0 let head5 = create_linked_list(vec![1, 2, 3, 4, 5]); let result5 = rotate_list_circular(head5, 0); assert_eq!(linked_list_to_vec(result5), vec![1, 2, 3, 4, 5]); }}package main
import "fmt"
type ListNode struct { Val int Next *ListNode}
// RotateListCircular rotates a linked list to the right by k positions using the circular approach.//// Approach:// 1. Calculate the effective rotation: k = k % length// 2. Create a circular list by connecting the tail to the head// 3. Find the new head position: walk (length - k) steps from the original head// 4. Break the circle at the appropriate point//// Time: O(n) - single pass to find length and establish circle, walk (length - k) steps// Space: O(1) - only using pointersfunc RotateListCircular(head *ListNode, k int) *ListNode { if head == nil || head.Next == nil || k == 0 { return head }
// Step 1: Find the length of the list and the tail length := 0 tail := head for tail.Next != nil { length++ tail = tail.Next } length++ // Add 1 for the tail node itself
// Step 2: Normalize k k = k % length if k == 0 { return head }
// Step 3: Create a circular list tail.Next = head
// Step 4: Find the new head position // After rotation by k, the new head is at position (length - k) // We need to walk (length - k) steps from the original head stepsToWalk := length - k current := head for i := 0; i < stepsToWalk-1; i++ { current = current.Next }
// Step 5: Break the circle newHead := current.Next current.Next = nil
return newHead}
// Helper function to create a linked list from a slicefunc CreateLinkedList(values []int) *ListNode { if len(values) == 0 { return nil } head := &ListNode{Val: values[0]} current := head for i := 1; i < len(values); i++ { current.Next = &ListNode{Val: values[i]} current = current.Next } return head}
// Helper function to convert linked list to slice for easy printingfunc LinkedListToSlice(head *ListNode) []int { var result []int current := head for current != nil { result = append(result, current.Val) current = current.Next } return result}
// Test casesfunc main() { // Test 1: [1, 2, 3, 4, 5], k=2 head1 := CreateLinkedList([]int{1, 2, 3, 4, 5}) result1 := RotateListCircular(head1, 2) fmt.Println(LinkedListToSlice(result1)) // [4, 5, 1, 2, 3]
// Test 2: [0, 1, 2], k=4 head2 := CreateLinkedList([]int{0, 1, 2}) result2 := RotateListCircular(head2, 4) fmt.Println(LinkedListToSlice(result2)) // [2, 0, 1]
// Test 3: [1], k=1 head3 := CreateLinkedList([]int{1}) result3 := RotateListCircular(head3, 1) fmt.Println(LinkedListToSlice(result3)) // [1]
// Test 4: [1, 2], k=2 head4 := CreateLinkedList([]int{1, 2}) result4 := RotateListCircular(head4, 2) fmt.Println(LinkedListToSlice(result4)) // [1, 2]
// Test 5: [1, 2, 3, 4, 5], k=0 head5 := CreateLinkedList([]int{1, 2, 3, 4, 5}) result5 := RotateListCircular(head5, 0) fmt.Println(LinkedListToSlice(result5)) // [1, 2, 3, 4, 5]}Interactive Visualization
Section titled “Interactive Visualization”Animated walkthrough
Watch how the algorithm identifies the break point and performs the rotation. The list is broken at position (length - k - 1), then reconnected to create the rotated list.
Approach 3: Optimized Two-Pointer
Section titled “Approach 3: Optimized Two-Pointer”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Rotate List"""
def solve(): """Implementation for approach 3 of Rotate List""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Rotate List// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Rotate List * Approach 3 */public class RotateListOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Rotate List * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Rotate List/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Rotate List// Approach 3
func main() {{ fmt.Println("Solution implementation")}}