演算法:排序連結串列:歸併排序

於對對發表於2020-11-21

題目
給定連結串列的頭結點 head ,請將其按 升序 排列並返回 排序後的連結串列 。

head = [4,2,1,3]
輸出:[1,2,3,4]

解題
1,最簡單的演算法,就是挨個遍歷連結串列,將其加入陣列,通過陣列排序。但這樣的空間複雜度比較高。
2,我們學過歸併排序。那就用歸併排序來解題。
概念:歸併排序就是有 n 個數字:2,4,1,5,3…
先兩個兩個的排序,再兩組兩組的排序。
在這裡插入圖片描述

程式碼

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null) {
            return head;
        }
        int length = 0;
        ListNode node = head;
        while (node != null) {
            length++;
            node = node.next;
        }
        ListNode dummyHead = new ListNode(0, head);
        for (int sublen=1;sublen<length;sublen<<=1){
            ListNode pre = dummyHead;
            ListNode curr = dummyHead.next;
            ListNode head1;
            ListNode head2;
            while (curr!=null){
                head1 = curr;
                for (int i=1;i<sublen && curr.next!=null;i++){
                    curr = curr.next;
                }
                head2 = curr.next;
                curr.next = null; // 斷開連結串列1
                curr = head2;
                for (int i=1;i<sublen && curr!=null && curr.next!=null;i++){
                    curr = curr.next;
                }
                ListNode next=null;// 用來儲存curr
                if (curr!=null){
                    next = curr.next;
                    curr.next = null; // 斷開連結串列2
                }
                ListNode mergeNode = merge(head1,head2);
                pre.next = mergeNode;
                while(pre.next!=null){
                    pre = pre.next;
                }
                curr = next;
            }
        }
        return dummyHead.next;
    }

    public ListNode merge(ListNode head1, ListNode head2) {
        ListNode dumpHead = new ListNode();
        ListNode temp = dumpHead;
        while (head1!=null && head2!=null){
            if (head1.val<head2.val){
                temp.next = head1;
                head1 = head1.next;
            } else {
                temp.next = head2;
                head2 = head2.next;
            }
            temp = temp.next;
        }
        if (head1!=null){
            temp.next = head1;
        }else if(head2!=null){
            temp.next = head2;
        }
        return dumpHead.next;
    }
}

相關文章