https://leetcode.com/problems/sort-list/
Sort a linked list in O(n log n) time using constant space complexity.
这道题按题目要求就只能用quicksort了,mergesort是需要O(n)额外空间的哈。
先定义partition代码:
以tail的值为seed,比seed小的放左边,比seed大的放右边,最后seed的值和比seed大的这部分里面第一个node交换,保证middle node的值是seed,但是因为在list里面求previous是比较难的,所以返回的不是值为seed的middle node,而是middle node的前一个node, premiddle。
因此下一轮就是
quicksort(head, premiddle);
quickSort(premiddle.next.next, tail);
需要注意的情况是,当中值左边没有的时候,也就是上一次partition中没有比seed小的值时,这时的premiddle返回的是head,也是真正的middle, 所以后半部分排序应该是quickSort(premiddle.next, tail).
当中值右边没有值时,也就是上一次partition中没有比seed大的值时,这里的premiddle是tail前一个node,middle还是tail,但是这时的premiddle.next.next就是不属于当前排序范围了,所以这种情况下就不用排后半部分了。
总之因为Linkedlist排序不像array那样可以比较head,tail的下标,所以在原array中 head>tail可以一下判断出不用再排了,但是在List中head就算到了tail后面,它也可能是个valid的node, 需要考虑这种情况,再处理。
在下面代码的partition函数中,less是middle,pre是premiddle。
代码里面全是值交换,不是node交换,因为node交换需要一个非常完善的swap()函数,容易错。。。不过下次可以试下用node交换。
public class Solution {
public ListNode sortList(ListNode head) {
if(head==null || head.next==null) return head;
ListNode tail = head;
while(tail.next!=null) tail = tail.next;
quickSort(head, tail);
return head;
}
public void quickSort(ListNode head, ListNode tail){
if(head == tail || head==null || tail==null) return;
ListNode premiddle = partition(head, tail);
if(premiddle!=head) quickSort(head, premiddle);
if(premiddle == head) quickSort(premiddle.next, tail);
else if(premiddle.next!=tail && premiddle.next.next!=tail) quickSort(premiddle.next.next, tail);
}
public ListNode partition(ListNode head, ListNode tail) {
int x = tail.val;
if(head==tail || head==null || head.next==null) return head;
ListNode traverse = head;
ListNode pre = head;
ListNode less = head;
while(traverse!=tail){
if(traverse.val < x){
int tmp = less.val;
less.val = traverse.val;
traverse.val = tmp;
pre = less;
less = less.next;
}
traverse = traverse.next;
}
int tmp = less.val;
less.val = tail.val;
tail.val = tmp;
return pre;
}
}