原题描述:https://oj.leetcode.com/problems/sort-list/
Sort a linked list in O(n log n) time using constant space complexity.
解题思路:
题目要求 O(n*lgn)的时间复杂度和常量的空间复杂度,来实现单链表的排序。
对于O(n*lgn)时间复杂度的排序算法,我们很容易就能想到快速排序、归并排序和堆排序。其中,快速排序要求能在常数时间内交换两个元素,这个单链表是无法实现的,所以排除之。堆排序需要O(n)的空间复杂度来建堆,所以也排除之。于是,我采用归并排序来实现。
单链表的归并排序,关键点就是链表的折半划分与合并。怎样来实现链表的折半划分呢?我们可以通过快慢指针法来实现,设定一个慢指针(步长为1)和快指针(步长为2),然后同步扫描链表,当快指针扫描到链表尾部时,由于快指针的步长是慢指针的2倍,所以慢指针所停在的位置就是链表的二分点。至于两个有序链表的合并,无非就是依次扫描对比,然后按序添加到新链表中。
代码实现:
public class Solution {
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public ListNode sortList(ListNode head) {
ListNode head1, head2;
if (head == null || head.next == null)
return head;
ListNode slow = head, fast = head;
while (fast != null && fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
head1 = head;
head2 = slow.next;
slow.next = null;
head1 = sortList(head1);
head2 = sortList(head2);
return merge(head1, head2);
}
private ListNode merge(ListNode head1, ListNode head2) {
if (head1 == null) {
return head2;
} else if (head2 == null) {
return head1;
}
ListNode head, index;
if (head1.val <= head2.val) {
head = head1;
head1 = head1.next;
} else {
head = head2;
head2 = head2.next;
}
index = head;
while (head1 != null && head2 != null) {
if (head1.val <= head2.val) {
index.next = head1;
head1 = head1.next;
} else {
index.next = head2;
head2 = head2.next;
}
index = index.next;
}
if (head1 != null) {
index.next = head1;
}
if (head2 != null) {
index.next = head2;
}
return head;
}
}