• LeetCode148. Sort List 单链表排序


    单链表排序

    以arr = [8,6,7,5,1,2]为例

    1. 自顶向下归并排序(递归)——分治法

    Time: O(NlogN)
    Space: O(LOG(N))

    • 自顶向下:

    (8->6->7) | (5->1->2)
    (8->6)|(7) | (5->1)|(2)
    (8)|(6)|(7) |(5)|(1)|(2)

    • 栈返回:

    (6->8)|(7) |(1->5) | (2)
    (6->7->8) | (1->2->5)
    (1->2->5->6->7->8)

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            if(!head || !head->next){
                return head;
            }
            ListNode* slow = head, *fast = head;
            while(fast->next && fast->next->next){
                slow = slow->next;
                fast = fast->next->next;
            }
            ListNode* right = slow->next;
            slow->next = nullptr;
            ListNode* left = head;
            ListNode* sortedLeft = sortList(left), *sortedRight = sortList(right);
            return merge(sortedLeft, sortedRight);        
        }
    
        ListNode* merge(ListNode* left, ListNode* right){
            ListNode dummyNode(0), *cur = &dummyNode;
            while(left && right){
                if(left->val < right->val){
                    cur->next = left;
                    left = left->next;
                    cur = cur->next;
                }else{
                    cur->next = right;
                    right = right->next;
                    cur = cur->next;
                }
            }
            cur->next = left ? left : right;
            return dummyNode.next;
        }
    };
    
    

    2. 自底向上归并排序 (空间O(1))

    Time: O(NLogN)
    Space: O(1)

    • 切分归并过程

    step = 1: dummy->(8->6->7->5->1->2)
    step = 1: dummy->(6->8) | (7->5->1->2)
    step = 1: dummy->(6->8->5->7) (1->2)
    step = 1: dummy->(6->8->5->7->1->2)
    step = 2: dummy->(5->6->7->8) | (1->2)
    ...
    dummy->(1->2->5->6->7->8)

    • 返回 dummy->next
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            if(!head || !head->next){ return head; }
            int length = 0;
            ListNode* cur = head;
            while(cur){
                cur = cur->next;
                length++;
            }
            ListNode newNode(0);
            newNode.next = head;
            for(int step = 1; step < length; step <<= 1){
                ListNode* pre = &newNode;
                cur = newNode.next;
                while(cur){
                    ListNode* left = cur;
                    ListNode* right = cutList(left, step);
                    cur = cutList(right, step);
                    pre->next = mergeList(left, right);
                    while(pre->next){
                        pre = pre->next;
                    }
                }
            }
            return newNode.next;
    
        }
    
        ListNode* cutList(ListNode* cur, int step){
            for(int i = 1; (i < step) && cur; ++i){
                cur = cur->next;
            }
            if(!cur) return nullptr;
            ListNode* nextNode = cur->next;
            cur->next = nullptr;
            return nextNode;
        }
    
        ListNode* mergeList(ListNode* left, ListNode* right){
            ListNode dummyNode(0), *cur = &dummyNode;
            while(left && right){
                if(left->val < right->val){
                    cur->next = left;
                    left = left->next;
                }else{
                    cur->next = right;
                    right = right->next;
                }
                cur = cur->next;
            }
            cur->next = left ? left : right;
            return dummyNode.next;
        }
    };
    

    3. 快速排序(元素个数较多且基本有序的情况下可能超时)

    Time: worst case, O(N^2)
    Space: O(N)

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            ListNode dummyNode(0);
            dummyNode.next = head;
            quickSort(&dummyNode, head, nullptr);
            return dummyNode.next;
        }
    
        void quickSort(ListNode* dummyNode, ListNode* head, ListNode* end){
            if(head != end){
                ListNode* pivot = getPivot(dummyNode, head);
                quickSort(dummyNode, dummyNode->next, pivot);
                quickSort(pivot, pivot->next, end);
            }
        }
    
        ListNode* getPivot(ListNode* dummyNode, ListNode* head){
            ListNode nodeR(0), nodeL(0);
            ListNode* cur = head->next, *pRight = &nodeR, *pLeft = &nodeL;
            int pivot = head->val;
            while(cur){
                if(cur->val < pivot){
                    pLeft->next = cur;
                    pLeft = pLeft->next;
                }else{
                    pRight->next = cur;
                    pRight = pRight->next;
                }
                cur = cur->next;
            }
            pRight->next = nullptr;
            head->next = nodeR.next;
            pLeft->next = head;
            dummyNode->next = nodeL.next;
            return dummyNode->next;
        }
    };
    
  • 相关阅读:
    JavaScript节点属性
    main函数的参数
    CGI
    open()函数 linux中open函数使用
    海伦公式
    C语言字符串操作函数
    makefile(一)
    makefile
    第一天
    时间小憩
  • 原文地址:https://www.cnblogs.com/qiangz/p/16439682.html
Copyright © 2020-2023  润新知