You are given the head of a singly linked list. Your task is to sort the linked list in ascending order and return the head of the sorted list.
[0, 5 * 10^4]
. The value of each node will be between -10^5 and 10^5Example 1:
Input: head = [4, 2, 1, 3]
Output: [1, 2, 3, 4]
Explanation: The input linked list has the values 4, 2, 1, and 3 in that order. The sorted linked list should have the values 1, 2, 3, and 4 in ascending order.
Example 2:
Input: head = [-1, 5, 3, 4, 0]
Output: [-1, 0, 3, 4, 5]
Explanation: The input linked list has the values -1, 5, 3, 4, and 0. The sorted linked list should have the values -1, 0, 3, 4, and 5 in ascending order.
Example 3:
Input: head = []
Output: []
Explanation: An empty linked list should return an empty linked list.
Can you sort the linked list in O(n log n) time and O(1) memory (i.e., constant space)?
The most straightforward approach is to extract all the values from the linked list into an array, sort the array, and then reconstruct a new sorted linked list (or modify the existing one). This method is easy to implement but not the most efficient.
Arrays.sort()
(which typically uses a variation of quicksort or merge sort).import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
public class Solution {
public ListNode sortList(ListNode head) {
List<Integer> values = new ArrayList<>();
ListNode current = head;
while (current != null) {
values.add(current.val);
current = current.next;
}
Collections.sort(values);
current = head;
int i = 0;
while (current != null) {
current.val = values.get(i++);
current = current.next;
}
return head;
}
}
The optimal solution is to use merge sort. Merge sort is well-suited for linked lists because it doesn't require random access (unlike quicksort, which is array-friendly but not ideal for linked lists).
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
public class Solution {
public ListNode sortList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode mid = getMid(head);
ListNode left = head;
ListNode right = mid.next;
mid.next = null;
left = sortList(left);
right = sortList(right);
return merge(left, right);
}
private ListNode getMid(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
private ListNode merge(ListNode list1, ListNode list2) {
ListNode dummyHead = new ListNode();
ListNode tail = dummyHead;
while (list1 != null && list2 != null) {
if (list1.val < list2.val) {
tail.next = list1;
list1 = list1.next;
} else {
tail.next = list2;
list2 = list2.next;
}
tail = tail.next;
}
if (list1 != null) {
tail.next = list1;
} else {
tail.next = list2;
}
return dummyHead.next;
}
}
null
.