1. Problem Summary
You are given the head of a singly linked list.
Your task is to sort the linked list in ascending order using the logic of insertion sort, and return the new head.
Important characteristics:
- Sorting must simulate insertion sort behavior
- You cannot index nodes directly (linked list limitation)
- You must adjust node pointers rather than swap values (best practice)
- The list may contain duplicates, negative values, or already sorted segments
Example interpretation:
For input:
4 → 2 → 1 → 3
Sorted output:
1 → 2 → 3 → 4
2. Key Insights
Why standard insertion sort fits linked lists
Insertion sort inserts elements into their correct place in a growing sorted region.
Linked lists allow efficient insertion when the insertion point is known.
Main strategy
Maintain two conceptual regions:
- A sorted portion at the beginning
- The remaining unsorted nodes
Each iteration extracts the next unsorted node and inserts it into the correct position in the sorted region.
Dummy head simplifies insertion logic
Using a dummy node avoids edge-case handling when inserting at the head.
Traversal rule for insertion position
For each node being inserted:
find first node in sorted region whose value > current.val insert before it
3. Approach
Linked list insertion sort with dummy head
Steps:
- Create a dummy head (
dummy) whose next points tonull - Traverse the original list with pointer
current - For each node:
- Store
nextNode = current.next - Find insertion point starting from
dummy - Insert the node into sorted position
- Move
current = nextNode
- Store
- Continue until entire list is processed
- Return
dummy.nextas sorted head
This guarantees correctness and handles insert-at-head cleanly.
4. Time and Space Complexity
Time Complexity: O(N²)
Worst case: descending list causes full scans for each insertion.
Space Complexity: O(1)
Sorting done in-place, no extra list storage used.
5. Java Solution
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode(0);
ListNode current = head;
while (current != null) {
ListNode nextNode = current.next;
// Find insertion position
ListNode prev = dummy;
while (prev.next != null && prev.next.val < current.val) {
prev = prev.next;
}
// Insert current node
current.next = prev.next;
prev.next = current;
// Move to next original node
current = nextNode;
}
return dummy.next;
}
}
6. Dry Run Examples
Example 1
Input:
4 → 2 → 1 → 3
Processing:
Start with dummy → []
Insert 4:
dummy → 4
Insert 2:
find position before 4
dummy → 2 → 4
Insert 1:
find position before 2
dummy → 1 → 2 → 4
Insert 3:
find position between 2 and 4
dummy → 1 → 2 → 3 → 4
Output:
1 → 2 → 3 → 4
Example 2
Input:
-1 → 5 → 3 → 4 → 0
Sorted result:
-1 → 0 → 3 → 4 → 5
Example 3 (already sorted)
Input:
1 → 2 → 3
Insertion positions always at end
Output same list
Example 4 (reverse sorted)
Input:
5 → 4 → 3 → 2 → 1
Worst-case behavior
Output:
1 → 2 → 3 → 4 → 5
7. Why This Solution Works
- Simulates insertion sort exactly
- Uses dummy head to simplify edge insertion
- Avoids value swapping (pointer manipulation preferred)
- Handles duplicates without special cases
- Works for all list lengths including size 0 or 1
8. Common Mistakes
- Forgetting to store
nextNodebefore insertion (loses remainder of list) - Trying to swap node values instead of inserting nodes
- Incorrectly resetting search pointer (must restart from dummy each time)
- Breaking sorted chain due to pointer misassignment
- Assuming array-style indexing works
