1. 程式人生 > >LeetCode刷題MEDIM篇 Sort List

LeetCode刷題MEDIM篇 Sort List

題目

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

十分鐘思考

對於nlogn的時間複雜度,必定採用遞迴,折半,分而治之的思想。從list中間劈開,然後遞迴分割,排序後逐次合併。

但是寫程式碼,不知道具體怎麼寫,看了其他人的實現,思路是對的,自己嘗試寫一遍。尤其是從中間分割list的方法,利用快慢指標,很厲害。一定要學會這個方法,之前判斷單鏈表是否有環,也是利用快慢指標。來,自己寫一下。程式碼一次通過,沒有一點問題。總結一下:

1,拆分list的方法,利用快慢指標

2  合併兩個單鏈表,從小到大排序。首先建立一個dummy node,作為新連結串列的開頭,然後一個新的curr指標,指向加入的node

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {
        //分而治之,從中間分開list
        //基準條件
        if(head==null||head.next==null){
            return head;
        }
        ListNode fast=head;
        ListNode slow=head;
        ListNode pre=slow;
        while(fast!=null&&fast.next!=null){
            //記錄斷開位置
            pre=slow;
            slow=slow.next;
            fast=fast.next.next;
        }
        //斷開list
        pre.next=null;
        //遞迴拆分
        ListNode nodeLeft=sortList(head);
        ListNode nodeRight=sortList(slow);
        //合併list,需要依次拼接,剛開始各有一個節點,然後會有多個,依次往上合併
        return merge(nodeLeft,nodeRight);
    }
    private ListNode merge(ListNode l1,ListNode l2){
        //一個dummynode,一個curr指標,依次比較新增到新連結串列,長度不同,剩下的加入就可以
        ListNode dummy=new ListNode(0);
        ListNode curr;
        curr=dummy;
        while(l1!=null&&l2!=null){
            if(l1.val<l2.val){
                curr.next=l1;
                l1=l1.next;
            }
            else{
                curr.next=l2;
                l2=l2.next;
            }
            curr=curr.next;
        }
        //如果長度不一樣
        if(l1!=null){
            curr.next=l1;
        }
        if(l2!=null){
            curr.next=l2;
        }
        return dummy.next;
    }
    
}