The problem is to write an algorithm to split a given linkedlist efficiently into three almost-equivalent linkedlists, i.e.
if we have a linkedlist {1->5->7->9->2->4->6} the output should be
LL_1={1->5->7}, LL_2={9->2}, LL_3={4->6}
My solution does the following:
1-iterate the given linkedlist from start to end
2-at each node cache the nodes reference into an array, say ll_array
3-now we have the linkedlists size (ll_array.lenght) and all the node references
in an array which we can use to create the three linkedlists in a
straightforward manner
but the above algorithm requires O(n) time and O(n) space. Can this be done better?
Solution:
based on hints from ChrisH. This alternative takes O(n) time but constant extra space (for the temporary holders)
Node {
String value;
Node next;
}
split(Node rootNode /*root node of input linked-list*/) {
// root node of the three resulting linked-lists
Node root_1 = rootNode;
Node root_2 = null;
Node root_3 = null;
// previous nodes of linked-lists 2 & 3 (since ours is a singly-linked-list)
Node prev_2 = null;
Node prev_3 = null;
int count = 0; // counter
Node currentNode = rootNode; // temp holder
while(currentNode != null) {
count++;
if (count > 3) {
int mod = count % 3;
if (mod == 1) {
prev_2 = root_2;
root_2 = root_2.next;
prev_3 = root_3;
root_3 = root_3.next;
} else if (mod == 2) {
prev_3 = root_3;
root_3 = root_3.next;
}
} else if (count == 2) { // initialize linked-list-2
root_2 = currentNode;
} else if (count == 3) { // initialize linked-list-3
root_3 = currentNode;
}
currentNode = currentNode.next;
}
// unlink linked-lists 2 & 3 from the chain
prev_2.next = null;
prev_3.next = null;
}
This sounds like homework so I’m going to provide a hint rather than a full answer.
You will not find an algorithm that runs in less than O(n) time because splitting something into equal size parts requires knowing the size of the whole, and finding the length of a linked list requires O(n).
But you can solve this problem with only O(1) extra space. The key to the solution is that you only need to find the points in the list where you need to cut it. Those points should be separated by roughly equal numbers of nodes.
Knowing the length of the list requires an iterator to visit every node. What is required to know 1/3 of the length and what is required to know 2/3 of the length? I think the answer will present itself if you think along those lines.