1. 程式人生 > >LeetCode--147. Insertion Sort List

LeetCode--147. Insertion Sort List

題目連結:https://leetcode.com/problems/insertion-sort-list/

要求給單鏈表進行插入排序,我們先回憶一下陣列A的插入排序:索引指標i開始於i=0或1,i之前的表示已經排好順序的陣列,A[i]向前逐個比較,遇到比A[i]大的元素則後移一個,直到遇到一個比A[i]小的元素A[j],則將A[i]放在A[j]後面。那麼我們來看看連結串列,單鏈表是不能向前移動,只能向後移動,需要一個類似於i的指標dect來限定已經排好序的範圍,而需要另一個指標來從頭結點開始尋找插入位置,而尋找插入位置相當於從頭結點開始尋找第一個比待插入值大的節點的前驅節點,這個前驅節點就是待插入節點的前驅,利用這個前驅才能進行插入操作。

值得注意的是,因為被插入節點的被插入位置可能在頭結點之前,所以常用技巧是設定一個虛擬節點。

還有就是如何找到那個被插入節點呢?當然是違反大小順序的相鄰節點的後者需要重新給它安排位置啦。看圖說話:

這是原連結串列:

找到第一個逆序元素的前驅detect,被插入元素為chosen:

從頭結點開始尋找第一個比待插入值大的節點的前驅節點:

然後執行插入操作:

重複上述操作:

最終得到一個排好序的連結串列:

程式碼如下:

class Solution {
    
    public ListNode insertionSortList(ListNode head) {
        
        if(head==null || head.next==null)
            return head;
        ListNode virtual=new ListNode(Integer.MIN_VALUE);
        virtual.next=head;
        
        ListNode detect=head;
        while(detect.next!=null)
        {
            if(detect.val<=detect.next.val)
                detect=detect.next;
            else
            {
                ListNode chosen=detect.next;
                ListNode pre=virtual;
                while(pre.next.val<chosen.val)
                    pre=pre.next;
                detect.next=chosen.next;
                chosen.next=pre.next;
                pre.next=chosen;
            }
        }
        return virtual.next;
    }
}

效率還是很高的!!!