Shift Linked List
Shift Linked List
Category
Linked Lists
Difficulty
Medium
Problem Statement
Given the head of a singly linked list and an integer k, shift the list by k positions. A positive k means shifting each node k positions forward (toward the tail), which effectively moves the last k nodes to the front. A negative k means shifting backward (the first |k| nodes move to the end). Return the head of the shifted list.
Intuition
Shifting a linked list by k positions is equivalent to finding the correct "cut point," detaching the list there, and reattaching the parts in reverse order. Since shifting by the length of the list results in the same list, we work with k modulo the list length to avoid unnecessary full rotations.
For a forward shift by k: the new head is the node at position (length - k) from the start, and the node just before it becomes the new tail.
Approach
- Calculate the length of the list and get a reference to the tail node.
- Compute the effective shift:
k = k % length. If k is 0, return the original head. - If k is negative, convert it to the equivalent positive shift:
k = k + length. - Find the new tail at position
length - k - 1from the head (0-indexed). - The new head is
newTail.next. - Set
newTail.next = nullto terminate the first part. - Set the original tail's
nextto the original head to connect the two parts. - Return the new head.
Pseudocode
function shiftLinkedList(head, k):
if head is null:
return null
length = 1
tail = head
while tail.next is not null:
tail = tail.next
length += 1
k = k % length
if k == 0:
return head
if k < 0:
k = k + length
newTail = head
for i from 1 to (length - k - 1):
newTail = newTail.next
newHead = newTail.next
newTail.next = null
tail.next = head
return newHead
Time & Space Complexity
- Time: O(n), where n is the length of the list. We traverse the list twice: once to find the length and tail, once to find the cut point.
- Space: O(1). Only a constant number of pointers are used.
Key Insights
- Taking k modulo the list length handles cases where k is larger than the list length or negative.
- A forward shift by k is the same as a backward shift by (length - k).
- The operation is essentially making the list circular temporarily, then cutting it at the right point.
- No nodes are created or destroyed; only pointer manipulations are needed.
Edge Cases
- k = 0 or k is a multiple of the list length: return the original list unchanged.
- k is negative: equivalent to shifting in the opposite direction.
- |k| is greater than the list length: the modulo operation handles this.
- Single-node list: any shift returns the same node.
- k equals the list length: the list remains unchanged.