
Problem Statement
The task is to sort a singly linked list using the insertion sort algorithm and return the head of the sorted linked list. Insertion sort, a straightforward and intuitive sorting algorithm, works by building a sorted array or list one item at a time by repeatedly removing an element from the input data and finding the appropriate spot for it within the already sorted section.
This method treats the list in two parts: the already sorted section, which initially contains only the first element, and the unsorted section, which includes all other elements. To integrate an element from the unsorted section, the algorithm removes it and inserts it into the correct position in the sorted section. This process repeats until all elements are neatly allocated in the sorted section, and the input list is fully sorted.
Examples
Example 1
Input:
head = [4,2,1,3]
Output:
[1,2,3,4]
Example 2
Input:
head = [-1,5,3,4,0]
Output:
[-1,0,3,4,5]
Constraints
- The number of nodes in the list is in the range
[1, 5000]
. -5000 <= Node.val <= 5000
Approach and Intuition
The insertion sort starts by assuming that the first element of the linked list is already sorted. Then, it proceeds with the following steps:
- Prepare a "dummy" node before the head of the original list, which helps handle edge cases, such as inserting a node at the head.
- Traverse the original linked list, beginning with the second element (since the first is assumed sorted).
- For each node in the original list, compare its value with those in the sorted part, from left to right, to find the appropriate insertion point.
- Adjust the pointers to accommodate the newly inserted node in the sorted list without losing the rest of the unsorted nodes.
The following examples illustrate this process:
Example 1:
- Input:
head = [4,2,1,3]
- Processing:
- Start with 4 as the sorted part.
- Insert 2, 1, and 3 in successive steps into their appropriate positions within the sorted part.
- Output:
[1,2,3,4]
– List after sorting using insertion sort.
- Input:
Example 2:
- Input:
head = [-1,5,3,4,0]
- Processing:
- Beginning with -1 as the sorted part.
- Insert 5, 3, 4, and 0 into the sorted part, making sure to maintain order after each insertion.
- Output:
[-1,0,3,4,5]
– A list rearranged from least to greatest value.
- Input:
Constraints Contextualization:
- The constraint that the list may contain up to 5000 nodes means our approach must be efficient enough to handle relatively large lists.
- The value range of the nodes, being from
-5000
to5000
, does not complicate our insertion logic, which is primarily concerned with relational rather than absolute values.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
ListNode* sortLinkedList(ListNode* start) {
ListNode* placeholder = new ListNode();
ListNode* pointer = start;
while (pointer != NULL) {
ListNode* temp = placeholder;
while (temp->next != NULL && temp->next->val <= pointer->val) {
temp = temp->next;
}
ListNode* subsequent = pointer->next;
pointer->next = temp->next;
temp->next = pointer;
pointer = subsequent;
}
return placeholder->next;
}
};
This code offers a C++ implementation of the insertion sort algorithm specifically adapted to sort a singly linked list. The method sortLinkedList
accepts a pointer to the beginning of the linked list and returns a pointer to the sorted linked list.
Here's an outline of how this function operates:
- A new placeholder node,
placeholder
, is created to ease the insertion process by temporarily holding the sorted part of the list. - A
pointer
is used to traverse through the original list, starting from its first node. - For each node pointed to by
pointer
, iterate through the already sorted part of the list (starting fromplaceholder
) using another pointer,temp
. - Locate the proper position in the sorted list to insert the current node by checking if the value of
temp->next
is less than or equal to the current node's value. - Insert the current node (
pointer
) in its correct position:- Disconnect it from the original list.
- Adjust pointers so it links correctly within the sorted part.
- Move the
pointer
to the next node in the original list to continue the sorting process. - Finally, return the next node of the placeholder, which points to the head of the newly sorted linked list.
This method effectively reorders the nodes without allocating any new nodes except for an initial temporary node, ensuring a space-efficient sorting process while maintaining the original data intact.
class Solution {
public ListNode sortInsertion(ListNode headNode) {
ListNode sortedHead = new ListNode();
ListNode iterate = headNode;
while (iterate != null) {
ListNode positionFinder = sortedHead;
while (positionFinder.next != null && positionFinder.next.val <= iterate.val) {
positionFinder = positionFinder.next;
}
ListNode upcomingNode = iterate.next;
iterate.next = positionFinder.next;
positionFinder.next = iterate;
iterate = upcomingNode;
}
return sortedHead.next;
}
}
The given Java solution sorts a linked list using the insertion sort algorithm. Insertion sort is a simple sorting algorithm that builds the final sorted array (or list in this case) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. However, it provides an excellent method to sort a linked list due to its inherent mechanism, which does not require backtracking.
Perform the following steps to understand the provided solution's mechanism:
- Create a new placeholder for the start of the sorted list (
sortedHead
), initializing an emptyListNode
. - Traverse through each node of the original list (
headNode
) with a pointer namediterate
. - For each node that
iterate
points to, find the correct position in the sorted list to insert the node. This is done using another pointer,positionFinder
, which starts from the beginning of the sorted list (sortedHead
). - Slide down the sorted list using
positionFinder
until finding the spot where the current node (iterate
's node) should reside. This condition is met when no further node fits the criteria, or the next node's value exceeds the current value. - Interchange references to insert the node from the unsorted part into the correct position in the sorted list.
- Continue this for every node until all nodes are sorted, ultimately omitting the placeholder node (
sortedHead
).
- Create a new placeholder for the start of the sorted list (
The function would return
sortedHead.next
, which points to the head of the newly sorted linked list. Consequently, the original list structure is repurposed to form a sorted list based on node values, achieving the sorting through in-place node rearrangement without additional memory for array manipulation.
struct ListNode* sortLinkedList(struct ListNode* headNode) {
struct ListNode* sortedHead = malloc(sizeof(struct ListNode));
sortedHead->next = NULL;
struct ListNode* currentNode = headNode;
while (currentNode != NULL) {
struct ListNode* positionNode = sortedHead;
while (positionNode->next != NULL && positionNode->next->val <= currentNode->val) {
positionNode = positionNode->next;
}
struct ListNode* nextNode = currentNode->next;
currentNode->next = positionNode->next;
positionNode->next = currentNode;
currentNode = nextNode;
}
return sortedHead->next;
}
The code provided implements the insertion sort algorithm for sorting a linked list in C. The function sortLinkedList
takes a pointer to the head of an unsorted singly linked list and returns a new list that is sorted in ascending order. Below is a step-by-step breakdown of how this function operates:
Initial setup involves creating a helper node,
sortedHead
, which acts as a placeholder to facilitate easier insertion into the sorted part of the list. This node initially points toNULL
.A
currentNode
pointer starts at the head of the unsorted list and traverses each node.For each
currentNode
, the code iterates through the already sorted list (starting fromsortedHead
) to find the correct insert position. This is achieved using apositionNode
which moves through the sorted list as long as its next node's value is less than or equal to the value ofcurrentNode
.Once the appropriate position is located,
currentNode
is inserted afterpositionNode
:nextNode
temporarily holds the next node in the unsorted list.- The current node is linked into the sorted list by adjusting pointers.
- The traversal pointer (
currentNode
) then moves tonextNode
, proceeding to the next node in the original list.
This process repeats until all nodes from the original list are examined and inserted appropriately into the sorted list.
Finally, the function returns the next node to
sortedHead
, effectively the head of the newly sorted list, excluding the initial placeholder node.
This efficient handling of linked list elements ensures that all nodes are sorted without the need for additional data structures, with the operations primarily involving re-linking existing nodes in a different order. This solution is robust for various list conditions, including empty or single-element lists.
var sortLinkedList = function (headNode) {
let dummyNode = new ListNode();
let current = headNode;
while (current !== null) {
let prevNode = dummyNode;
while (prevNode.next !== null && prevNode.next.val <= current.val) {
prevNode = prevNode.next;
}
let nextNode = current.next;
current.next = prevNode.next;
prevNode.next = current;
current = nextNode;
}
return dummyNode.next;
};
The provided JavaScript code efficiently sorts a linked list using the insertion sort algorithm. To understand the solution implemented in the code:
- Initiate a
dummyNode
to facilitate easier handling of the head of the linked list, particularly when insertion happens at the head. - Define
current
to navigate through the original list from the headNode.
Proceed with the sorting process with the following detailed steps:
- Use a while loop to process each node in the list denoted by
current
. The loop continues untilcurrent
becomes null, indicating the end of the list. - Inside the loop, another nested while loop is utilized. Define
prevNode
starting fromdummyNode
to find the correct position to insert the current node. This loop continues as long as the next node ofprevNode
exists and its value is less than or equal to the value ofcurrent
. - Set
nextNode
to point to the next node ofcurrent
, which will become the newcurrent
node in the subsequent iteration. - Insert
current
into the new position by adjusting thenext
pointers:current.next
will point toprevNode.next
and then updateprevNode.next
to point tocurrent
. - Move to the next node in the original list by updating
current
tonextNode
.
The sorted linked list is obtained from dummyNode.next
, effectively skipping the dummy node used for insertion handling.
This code provides a robust method for sorting elements of a linked list where space complexity is minimized by reusing existing nodes, and the algorithm manages in-place sorting with a time complexity typically of O(n^2) in the worst case. This method is particularly useful when you need a stable sort without additional memory overhead, suitable for applications with limited memory resources.
class Solution:
def sortLinkedList(self, node: ListNode) -> ListNode:
placeholder = ListNode()
point = node
while point:
prev_node = placeholder
# Locate where to insert the current node
while prev_node.next and prev_node.next.val <= point.val:
prev_node = prev_node.next
subsequent = point.next
# Perform the insert operation
point.next = prev_node.next
prev_node.next = point
# Advance to the next node in the list
point = subsequent
return placeholder.next
The provided Python code implements the insertion sort algorithm to sort a linked list. The insertion sort is a straightforward algorithm that builds the final sorted linked list one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort or merge sort. However, the advantage of insertion sort is its simplicity and that it sorts in place, using a constant amount of additional space.
Here's a breakdown of the process:
- A placeholder node is created to act as the start of the sorted linked list.
- An iteration is initialized with the first node of the provided list.
- During each iteration of the while loop, the algorithm looks for the correct position to insert the current node to maintain the order:
- It systematically compares the current node's value with the sorted nodes' values.
- Finds the correct insertion point.
- Once the correct position is identified:
- The current node is then linked appropriately by adjusting the next pointers.
- The link adjustment is made:
- The current node points to its succeeding nodes in the already-sorted portion of the linked list ensuring order is maintained.
- The pointer of the preceding sorted node is adjusted to point to the current node effectively inserting it.
- The pointer moves to the next node in the list and the process is repeated until all nodes are processed and placed in order.
- The sorted linked list, which starts from the placeholder's next node, is then returned.
This code effectively allows a linked list to be sorted in ascending order without using additional lists or arrays, only rearranging the nodes by changing their pointers.
No comments yet.