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
思路来源于评论区:
class Solution {
public ListNode sortList(ListNode head) {
if ( head == null || head.next == null) return head;
ListNode preend = null;
ListNode slow = head;
ListNode fast = head;
//将原链表分为两个链表
while( fast != null && fast.next != null )
{
preend = slow;
slow = slow.next;
fast = fast.next.next;
}
preend.next = null;
//对两个链表分别进行排序
ListNode l1 = sortList(head);
ListNode l2 = sortList(slow);
//将排序后的子链表归并
return merge(l1, l2);
}
private ListNode merge(ListNode head1, ListNode head2)
{
ListNode helper = new ListNode(0);
ListNode newhead = helper;
while ( head1 != null && head2 != null )
{
if ( head1.val <= head2.val )
{
newhead.next = head1;
newhead = newhead.next;
head1 = head1.next;
}
else
{
newhead.next = head2;
newhead = newhead.next;
head2 = head2.next;
}
}
newhead.next = head1 == null ? head2 : head1;
return helper.next;
}
}
另一种解法:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head == null) return head;
ListNode dummy = new ListNode(0);
dummy.next = head;
int n = 1;
while(head.next != null)
{
head = head.next;
n++;
}
for(int step = 1; step < n; step *= 2)
{
ListNode prev = dummy;
ListNode cur = dummy.next;
while(cur != null)
{
ListNode left = cur;
ListNode right = split(left, step);
cur = split(right, step);
prev = merge(left, right, prev);
}
}
return dummy.next;
}
private ListNode split(ListNode prev, int step)
{
if(prev == null) return prev;
for(int i = 1; prev.next != null && i < step; i++)
{
prev = prev.next;
}
ListNode res = prev.next;
prev.next = null;
return res;
}
private ListNode merge(ListNode left, ListNode right, ListNode prev)
{
while(left != null && right != null)
{
if(left.val < right.val)
{
prev.next = left;
left = left.next;
}
else
{
prev.next = right;
right = right.next;
}
prev = prev.next;
}
if(left != null) prev.next = left;
else if(right != null) prev.next = right;
while(prev.next != null) prev = prev.next;
return prev;
}
}