题目来源:https://leetcode.com/problems/sort-list/
问题描述
Medium
Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3
Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0
Output: -1->0->3->4->5
------------------------------------------------------------
题意
链表归并排序。
------------------------------------------------------------
思路
不同于数组,链表随机访问的复杂度是O(n),因此注定了类似堆排序、快速排序这些基于数组随机访问的排序算法在链表上达不到它们在数组上的性能。而归并排序恰好只涉及顺序访问不涉及随机访问,因此归并排序在链表上的时间复杂度仍是O(nlogn)的。而且,链表的归并排序的merge过程只需要O(1)的内存,相比数组归并排序merge过程需要O(n)的内存,可见归并排序更适合链表。
具体实现上,仍是实现merge方法和mergeSort方法,其中mergeSort递归调用两个mergeSort分别处理链表的前半段和链表的后半段,merge将两个排序好的链表合成一个链表。
关于链表有一些特殊的处理技巧。例如从原来的链表新建链表可以new一个辅助的链表头,新链表头是这个辅助链表头的后继节点(见38行的注释); 找一个链表的中点可以用快慢指针的方法在一个循环之内搞定,快指针一次走两步,慢指针一次走一步,最后快指针走到头了,慢指针就到了链表中点(见第17行注释,要注意慢指针初始化为链表头,快指针初始化为链表头的后继节点,还有就是要注意快指针在循环体内的判空)。
------------------------------------------------------------
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode sortList(ListNode head)
{
if (head == null || head.next == null)
{
return head;
}
ListNode fast = head.next, slow = head;
// Compute mid node of list using fast & slow pointer
// Every time slow pointer goes 1 step while fast pointer goes 2 steps
// Mid node is stored in slow pointer
while (fast != null)
{
fast = fast.next;
if (fast != null)
{
fast = fast.next;
slow = slow.next;
}
}
ListNode h2 = sortList(slow.next);
slow.next = null;
ListNode h1 = sortList(head);
return merge(h1, h2);
}
public ListNode merge(ListNode h1, ListNode h2)
{
ListNode p1 = h1, p2 = h2, newHead = new ListNode(0), h = newHead;
// newHead: use an auxiliary head for new list
while (p1 != null && p2 != null)
{
if (p1.val < p2.val)
{
ListNode tmp = p1;
p1 = p1.next;
h.next = tmp;
h = h.next;
}
else
{
ListNode tmp = p2;
p2 = p2.next;
h.next = tmp;
h = h.next;
}
}
while (p1 != null)
{
ListNode tmp = p1;
p1 = p1.next;
h.next = tmp;
h = h.next;
}
while (p2 != null)
{
ListNode tmp = p2;
p2 = p2.next;
h.next = tmp;
h = h.next;
}
h.next = null;
return newHead.next;
}
}