🧠
Brute Force (Count and Split with Multiple Passes)
💡 This approach is straightforward and helps beginners understand the problem by breaking it down into simple steps, even if it is not the most efficient.
Intuition
First, count the total number of nodes. Then, calculate the size of each part and the remainder. Finally, iterate through the list multiple times to split it into parts accordingly.
Algorithm
- Traverse the linked list to count the total number of nodes.
- Calculate the base size of each part as total_nodes // k and the remainder as total_nodes % k.
- For each part, assign base size plus one extra node if remainder is still positive, then decrement remainder.
- Traverse the list again to cut the list into parts of the calculated sizes and store their heads.
💡 The challenge is to carefully track the sizes and correctly break the links to form separate parts without losing nodes.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def splitListToParts(head, k):
# Step 1: Count total nodes
total_nodes = 0
current = head
while current:
total_nodes += 1
current = current.next
# Step 2: Calculate size and remainder
part_size = total_nodes // k
remainder = total_nodes % k
parts = []
current = head
# Step 3: Split the list
for i in range(k):
head_part = current
size = part_size + (1 if remainder > 0 else 0)
if remainder > 0:
remainder -= 1
# Step 4: Move current pointer size-1 times
for j in range(size - 1):
if current:
current = current.next
# Cut the list if needed
if current:
next_part = current.next
current.next = None
current = next_part
parts.append(head_part)
return parts
# Driver code to test
if __name__ == '__main__':
# Helper to create linked list
def create_linked_list(arr):
dummy = ListNode(0)
curr = dummy
for val in arr:
curr.next = ListNode(val)
curr = curr.next
return dummy.next
head = create_linked_list([1,2,3,4,5,6,7,8,9,10])
k = 3
parts = splitListToParts(head, k)
for part in parts:
vals = []
while part:
vals.append(part.val)
part = part.next
print(vals)
Line Notes
total_nodes = 0Initialize counter to count nodes in the list
while current:Traverse entire list to get total length
part_size = total_nodes // kCalculate minimum size each part should have
remainder = total_nodes % kCalculate how many parts get an extra node
for i in range(k):Iterate over each part to build it
size = part_size + (1 if remainder > 0 else 0)Assign extra node to first 'remainder' parts
if remainder > 0: remainder -= 1Decrease remainder after assigning extra node
for j in range(size - 1):Move pointer to the last node of current part
current.next = NoneBreak the link to separate current part from the rest
parts.append(head_part)Add head of current part to result list
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
public class Solution {
public ListNode[] splitListToParts(ListNode head, int k) {
int totalNodes = 0;
ListNode current = head;
// Count total nodes
while (current != null) {
totalNodes++;
current = current.next;
}
int partSize = totalNodes / k;
int remainder = totalNodes % k;
ListNode[] parts = new ListNode[k];
current = head;
for (int i = 0; i < k; i++) {
ListNode headPart = current;
int size = partSize + (remainder > 0 ? 1 : 0);
if (remainder > 0) remainder--;
for (int j = 0; j < size - 1; j++) {
if (current != null) current = current.next;
}
if (current != null) {
ListNode nextPart = current.next;
current.next = null;
current = nextPart;
}
parts[i] = headPart;
}
return parts;
}
// Driver code
public static void main(String[] args) {
Solution sol = new Solution();
ListNode head = new ListNode(1);
ListNode curr = head;
for (int i = 2; i <= 10; i++) {
curr.next = new ListNode(i);
curr = curr.next;
}
ListNode[] parts = sol.splitListToParts(head, 3);
for (ListNode part : parts) {
ListNode temp = part;
System.out.print("[");
while (temp != null) {
System.out.print(temp.val);
temp = temp.next;
if (temp != null) System.out.print(",");
}
System.out.println("]");
}
}
}
Line Notes
int totalNodes = 0;Initialize node count
while (current != null)Count total nodes in list
int partSize = totalNodes / k;Calculate base size of each part
int remainder = totalNodes % k;Calculate how many parts get an extra node
for (int i = 0; i < k; i++)Loop over each part to build it
int size = partSize + (remainder > 0 ? 1 : 0);Assign extra node to first remainder parts
if (remainder > 0) remainder--;Decrement remainder after assigning extra node
for (int j = 0; j < size - 1; j++)Move pointer to last node of current part
current.next = null;Break link to separate current part
parts[i] = headPart;Store head of current part
#include <iostream>
#include <vector>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* head, int k) {
int totalNodes = 0;
ListNode* current = head;
// Count total nodes
while (current) {
totalNodes++;
current = current->next;
}
int partSize = totalNodes / k;
int remainder = totalNodes % k;
vector<ListNode*> parts(k, nullptr);
current = head;
for (int i = 0; i < k; i++) {
ListNode* headPart = current;
int size = partSize + (remainder > 0 ? 1 : 0);
if (remainder > 0) remainder--;
for (int j = 0; j < size - 1; j++) {
if (current) current = current->next;
}
if (current) {
ListNode* nextPart = current->next;
current->next = nullptr;
current = nextPart;
}
parts[i] = headPart;
}
return parts;
}
};
// Helper to create linked list
ListNode* createLinkedList(const vector<int>& vals) {
ListNode dummy(0);
ListNode* curr = &dummy;
for (int v : vals) {
curr->next = new ListNode(v);
curr = curr->next;
}
return dummy.next;
}
// Helper to print parts
void printParts(const vector<ListNode*>& parts) {
for (auto part : parts) {
cout << "[";
ListNode* curr = part;
while (curr) {
cout << curr->val;
curr = curr->next;
if (curr) cout << ",";
}
cout << "]\n";
}
}
int main() {
Solution sol;
ListNode* head = createLinkedList({1,2,3,4,5,6,7,8,9,10});
int k = 3;
vector<ListNode*> parts = sol.splitListToParts(head, k);
printParts(parts);
return 0;
}
Line Notes
int totalNodes = 0;Initialize count of nodes
while (current)Traverse list to count nodes
int partSize = totalNodes / k;Calculate base size per part
int remainder = totalNodes % k;Calculate how many parts get extra node
for (int i = 0; i < k; i++)Loop over each part to build
int size = partSize + (remainder > 0 ? 1 : 0);Assign extra node to first remainder parts
if (remainder > 0) remainder--;Decrement remainder after assignment
for (int j = 0; j < size - 1; j++)Move pointer to last node of current part
current->next = nullptr;Break link to separate current part
parts[i] = headPart;Store head of current part
function ListNode(val, next = null) {
this.val = val;
this.next = next;
}
function splitListToParts(head, k) {
let totalNodes = 0;
let current = head;
// Count total nodes
while (current !== null) {
totalNodes++;
current = current.next;
}
let partSize = Math.floor(totalNodes / k);
let remainder = totalNodes % k;
const parts = new Array(k).fill(null);
current = head;
for (let i = 0; i < k; i++) {
let headPart = current;
let size = partSize + (remainder > 0 ? 1 : 0);
if (remainder > 0) remainder--;
for (let j = 0; j < size - 1; j++) {
if (current !== null) current = current.next;
}
if (current !== null) {
let nextPart = current.next;
current.next = null;
current = nextPart;
}
parts[i] = headPart;
}
return parts;
}
// Helper to create linked list
function createLinkedList(arr) {
let dummy = new ListNode(0);
let curr = dummy;
for (let val of arr) {
curr.next = new ListNode(val);
curr = curr.next;
}
return dummy.next;
}
// Test
const head = createLinkedList([1,2,3,4,5,6,7,8,9,10]);
const k = 3;
const parts = splitListToParts(head, k);
for (const part of parts) {
let vals = [];
let curr = part;
while (curr !== null) {
vals.push(curr.val);
curr = curr.next;
}
console.log(vals);
}
Line Notes
let totalNodes = 0;Initialize node count
while (current !== null)Traverse list to count nodes
let partSize = Math.floor(totalNodes / k);Calculate base size per part
let remainder = totalNodes % k;Calculate how many parts get extra node
for (let i = 0; i < k; i++)Loop over each part to build
let size = partSize + (remainder > 0 ? 1 : 0);Assign extra node to first remainder parts
if (remainder > 0) remainder--;Decrement remainder after assignment
for (let j = 0; j < size - 1; j++)Move pointer to last node of current part
current.next = null;Break link to separate current part
parts[i] = headPart;Store head of current part
TimeO(n + k)
SpaceO(k) for output array
We traverse the list once to count nodes (O(n)) and once more to split into parts (O(n)). The output array has size k.
💡 For n=100 and k=5, we do about 200 steps plus 5 for output, which is efficient enough for interviews.
Interview Verdict: Accepted
This approach is simple and accepted, but can be improved by combining counting and splitting in one pass.