• 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;   
        }
        
    };
  • 相关阅读:
    使用物化视图的方式进行表级数据同步示例
    【闲谈】我的大学
    firefox的window.onerror没有详细的出错提示
    完全搞懂傅里叶变换和小波(3)——泰勒公式及其证明
    [VC6 console]调用API获取手机归属地
    灰度直方图及处理“cvQueryHistValue_1D”: 找不到标识符”的问题(上)
    【高级】C++中虚函数机制的实现原理
    jquery小例子
    VBA Promming——入门教程
    Wikidata和SparQL简介
  • 原文地址:https://www.cnblogs.com/qiaozhoulin/p/4585401.html
Copyright © 2020-2023  润新知