148. Sort Lis(链表中的归并排序)

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;   
    }
    
};

 

posted @ 2015-06-18 11:31  linqiaozhou  阅读(10587)  评论(0编辑  收藏  举报