Before attempting this problem, you should be comfortable with:
next pointers to null to create separate partsn / k) and distribute remainder (n % k)To split the list into k parts as evenly as possible, we first need to know the total length. Converting the linked list to an array gives us random access, making it easy to determine where each part starts and ends. Each part gets n / k elements at minimum, and the first n % k parts get one extra element to distribute the remainder evenly.
base_len = n / k (minimum elements per part) and remainder = n % k (parts that get an extra element).k parts:arr[start].start + base_len - 1, plus 1 if this part gets an extra element.arr[tail].next = null.start for the next part.# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
arr, cur = [], head
while cur:
arr.append(cur)
cur = cur.next
N = len(arr)
base_len, remainder = N // k, N % k
res = [None] * k
start = 0
for i in range(k):
if start < N:
res[i] = arr[start]
tail = start + base_len - 1
if remainder:
tail += 1
remainder -= 1
arr[tail].next = None
start = tail + 1
return resWe can avoid the extra array by working directly with the linked list. First, count the total nodes. Then traverse again, splitting the list into parts by tracking the current node and severing links at the appropriate positions. The first remainder parts each have one more node than the remaining parts.
base_len = length / k and remainder = length % k.k parts:base_len - 1 + (1 if remainder > 0 else 0) steps to reach the tail.curr.next, set curr.next = null to sever, then continue from the saved node.remainder after each extra-length part.# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
length, curr = 0, head
while curr:
curr = curr.next
length += 1
base_len, remainder = length // k, length % k
curr, res = head, []
for i in range(k):
res.append(curr)
for j in range(base_len - 1 + (1 if remainder else 0)):
if not curr:
break
curr = curr.next
remainder -= 1 if remainder else 0
if curr:
curr.next, curr = None, curr.next
return resAfter determining where each part ends, you must set the tail node's next pointer to null. Failing to do this leaves the parts still connected, causing the output to contain overlapping or incorrectly sized lists instead of independent segments.
When n % k != 0, the first remainder parts should each have one extra node. A common mistake is distributing extra nodes to the wrong parts (e.g., the last parts instead of the first) or failing to decrement the remainder counter properly, resulting in unevenly sized parts.
When there are more parts than nodes, some parts must be empty (null). Forgetting to account for this case can lead to index out of bounds errors or incorrect assignments when trying to set heads for parts that have no nodes.