LeetCode--------Sort List

LeetCode上的Sort List题目:

题目的意思很简单:将一个链表以O(nlogn)的时间复杂度排好序,并且使用常数空间。


关于排序算法的选择:这里我犯了个错误,就是将快速排序的时间复杂度记成了O(nlogn)。。。。(由于对快速排序比较熟悉-,-!)。但是实际情况是如果主元选择不当,最坏的情况会达到O(n2)。而且LeetCode上好像也特意针对快排做了测试用例,所以用快排会TLE。所以要使用归并排序,这种算法性能比较稳定,都是O(nlogn)。


这里做一个补充:虽然归并排序性能比较稳定,但是查资料可知,最常用的还是快排,归并排序的话,需要一定的辅助空间。对于快排,如果随机选择主元的话,快排的最坏情况出现的概率会随数据增多而大大减小,所以一般使用快排。


这里贴出我的代码(包含了快排和归并排序)---------------------(俩算法写了一晚上,想想没脸见人了。。。。)

关于归并的思想是记录本次要排序的链表长度,然后如果长度小于3,就合并,否则就递归排序,之后再合并。注意的地方是一定要先排序右边的链表,这样才能保证preHead的正确性。


/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {

    public ListNode sortList(ListNode head) {

        ListNode fakeHead = new ListNode(Integer.MIN_VALUE);//To avoid null of the preHead
        fakeHead.next = head;
        ListNode p = head;
        int n = 0;
        while(p != null){
            n++;
            p = p.next;
        }
        return mergeSort(fakeHead , head , n);

    }

    public ListNode mergeSort(ListNode preHead , ListNode head , int len){
        //如果len为1,2,那么归并为一个list,返回两个list的新head
        if(len == 1){
            return head;
        }
        if(len == 2){
            if(head.val > head.next.val){
                ListNode temp = head.next.next;
                preHead.next = head.next;
                preHead.next.next = head;
                head.next = temp;
            }
            return preHead.next;
        }
        //对两个list进行mergeSort
        int newLen1 = len / 2;
        int newLen2 = len - newLen1;
        ListNode p = head;
        for(int i = 1 ; i < newLen1 ; i++) {
            p = p.next;
        }
        //Must in the sequence of right----left
        ListNode newHead2 = mergeSort(p,p.next,newLen2);
        ListNode newHead1 = mergeSort(preHead,head,newLen1);
        
        //Merge
        ListNode newHead = null;
        if(newHead1.val < newHead2.val){
            newHead = newHead1;
            newHead1 = newHead1.next;
            newLen1--;
        }else{
            newHead = newHead2;
            newHead2 = newHead2.next;
            newLen2--;
        }
        preHead.next = newHead;
        while(newLen1 > 0 && newLen2 > 0){
            if(newHead1.val < newHead2.val){
                newHead.next = newHead1;
                newHead1 = newHead1.next;
                newHead = newHead.next;
                newLen1--;
            }else{
                newHead.next = newHead2;
                newHead2 = newHead2.next;
                newHead = newHead.next;
                newLen2--;
            }
        }

        if(newLen1 == 0){
            newHead.next = newHead2;
        }

        if(newLen2 == 0){
            newHead.next = newHead1;
            newLen1--;
            //newHead1 = newHead1.next;
            while(newLen1 >= 1){
                newHead1 = newHead1.next;
                newLen1--;
            }
            newHead1.next = newHead2;
        }

        return preHead.next;

    }

    public ListNode quickSort(ListNode head ,ListNode start ,ListNode end){
        if(head ==end || head.next == end)
            return head;
        //choose the first one
        ListNode nHead = head;
        ListNode previous = head;
        ListNode p = head.next;
        ListNode npivot = head;
        while(true){
            if(p == end){
                break;
            }
            if(p.val <= npivot.val){
                ListNode temp = p.next;
                previous.next = temp;
                p.next = nHead;
                //npivot.next = temp;
                if(start != null)
                    start.next = p;
                nHead = p;
                p = temp;
            }else{
                previous = p;
                p = p.next;
            }
        }
        if(start == null)
            nHead = quickSort(nHead , start , npivot);
        else {
            quickSort(nHead, start, npivot);
        }
        quickSort(npivot.next , npivot , end);
        return nHead;
    }

    ///////////////////////////////////////////////////
    ////////////////////TEST//////////////////////////
    public static void main(String[] args){
        Solution obj = new Solution();
        ListNode h = obj.create(new int[]{7,5,4,6,3,2,1});
        print(h);
        h = obj.sortList(h);
        print(h);
    }

    public ListNode create(int[] array){
        ListNode temp = new ListNode(array[0]);
        ListNode head = temp;
        for(int i = 1 ; i < array.length ; i++){
            ListNode t = new ListNode(array[i]);
            temp.next = t;
            temp = t;
        }
        return head;
    }

    public static void print(ListNode head){
        ListNode p = head;
        while(p != null){
            System.out.println(p.val);
            p = p.next;
        }
    }

}


class ListNode{
    int val;
    ListNode next;
    public ListNode(int val){
        this.val = val;
        next = null;
    }
}


你可能感兴趣的:(java,LeetCode,算法,归并排序,快速排序)