Sort a linked list in O(n log n) time using constant space complexity.
O(n log n) complexity are merge sort and quick sort. So in this problem, we can use merge sort to handle!
Different from array data, this problem requires good understanding of linked list operations, e.g., split, merge. Before doing this problem, I suggest you first check out the problem "Merge Two Sorted List" and "Linked List Cycle", and also the merge sort algorithm itself. Then the problem becomes pretty straightforward.
Like the merge sort, we can do recursively:
(1) Split the list (slow fast pointers)
(2) sort the first part (merge sort)
(3) sort the second part (merge sort)
(4) merge the two parts (merge two sorted lists)
java
public ListNode sortList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode middleNode = getMiddleNode(head);
ListNode next = middleNode.next;
middleNode.next = null;
return mergeTwoLists(sortList(head), sortList(next));
}
public ListNode getMiddleNode(ListNode head){
ListNode slow = head;
ListNode fast = head;
while(fast.next!=null&& fast.next.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode temp = new ListNode(0);
ListNode prev = temp;
while(l1!=null && l2!=null){
if(l1.val>l2.val){
prev.next = l2;
l2 = l2.next;
}
else{
prev.next = l1;
l1 = l1.next;
}
prev = prev.next;
}
if(l1!=null)
prev.next = l1;
else if(l2!=null)
prev.next = l2;
return temp.next;
}
c++
ListNode *sortList(ListNode *head) {
if(head == NULL || head->next == NULL) return head;
int len = 1;
ListNode *p = head;
while(p->next != NULL){
len++;
p = p->next;
}
ListNode *newHead = Sort(&head, len);
}
ListNode *Sort(ListNode **head, int lenght){
if(lenght == 1){
ListNode *temp = *head;
*head = (*head)->next;
temp->next = NULL;
return temp;
}
ListNode *leftHead = Sort(head,lenght/2);
ListNode *rightHead = Sort(head,lenght-lenght/2);
ListNode *newHead = merge2Lists(leftHead,rightHead);
return newHead;
}
ListNode *merge2Lists(ListNode *head1, ListNode *head2){
ListNode *head = new ListNode(INT_MIN);
ListNode *pre = head;
while(head1 != NULL && head2 != NULL){
if(head1->val <= head2->val){
pre->next = head1;
head1 = head1->next;
}else{
pre->next = head2;
head2 = head2->next;
}
pre = pre->next;
}
if(head1 != NULL){
pre->next = head1;
}
if(head2 != NULL){
pre->next = head2;
}
return head->next;
}