Sort List——經典(鏈表中的歸並排序)


Sort a linked list in O( n log n) time using constant space complexity.
  
對一個鏈表進行排序,且時間復雜度要求為 O(n log n) ,空間復雜度為常量。一看到 O(n log n) 的排序,首先應該想到歸並排序和快速排序,但是通常我們使用這兩種排序方法時都是針對數組的,現在是鏈表了。
        歸並排序法:在動手之前一直覺得空間復雜度為常量不太可能,因為原來使用歸並時,都是 O(N)的,需要復制出相等的空間來進行賦值歸並。對於鏈表,實際上是可以實現常數空間占用的(鏈表的歸並排序不需要額外的空間)。利用歸並的思想,遞歸地將當前鏈表分為兩段,然后merge,分兩段的方法是使用 fast-slow 法,用兩個指針,一個每次走兩步,一個走一步,知道快的走到了末尾,然后慢的所在位置就是中間位置,這樣就分成了兩段。merge時,把兩段頭部節點值比較,用一個 p 指向較小的,且記錄第一個節點,然后 兩段的頭一步一步向后走,p也一直向后走,總是指向較小節點,直至其中一個頭為NULL,處理剩下的元素。最后返回記錄的頭即可。
主要考察3個知識點,
知識點1:歸並排序的整體思想
知識點2:找到一個鏈表的中間節點的方法
知識點3:合並兩個已排好序的鏈表為一個新的有序鏈表

歸並排序的基本思想是:找到鏈表的middle節點,然后遞歸對前半部分和后半部分分別進行歸並排序,最后對兩個以排好序的鏈表進行Merge。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head==NULL||head->next==NULL)
            return head;
        return mergeSort(head);
    }
    ListNode* mergeSort(ListNode*head)
    {
        if(head->next==NULL)
            return head;
        ListNode* pHead,*qHead,*pre;
        pHead=head;
        qHead=head;
        pre=NULL;
        while(qHead!=NULL&&qHead->next!=NULL)
        {
           qHead=qHead->next->next;
           pre=pHead;
           pHead=pHead->next;
        }
        pre->next=NULL;
        ListNode *l,*r;
        l=mergeSort(head);
        r=mergeSort(pHead);
        return merge(l,r);
    }
    ListNode* merge(ListNode *l,ListNode*r)
    {
        ListNode *pRes=new ListNode(0);
        ListNode *temp=pRes;
        while(l!=NULL&&r!=NULL)
        {
            if(l->val<=r->val)
            {
                temp->next=l;
                temp=temp->next;
                l=l->next;
            }
            else
            {
                temp->next=r;
                temp=temp->next;
                r=r->next;
            }
        }
        if(l!=NULL)
            temp->next=l;
        if(r!=NULL)
            temp->next=r;
        temp=pRes->next;
        delete pRes;
        return temp;   
    }
    
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM