zoukankan      html  css  js  c++  java
  • Sort List leetcode

    这个题一开始本想用快速排序的,但是想了20分钟都没有头绪,难点在于快速排序的随机访问无法用链表实现,不过如果可以实现快速排序partition函数就可以了,但是这可能比较复杂,于是改用其他排序方法,上网查了下,大部分都采用了归并排序,归并排序并不需要有跨度的访问元素,可能唯一耗时的就是寻找中间点,这个可以利用两个指针,一个指针是另一个指针移动速度两倍来找到中间节点。

    首先采用自顶向下的递归方法实现:

    // Definition for singly-linked list.
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    
    ListNode *merge(ListNode *l1, ListNode *l2)
    {
        ListNode temp(0);
        ListNode *cur = &temp;
        while (l1 != nullptr && l2 != nullptr)
        {
            if (l1->val < l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        if (l1 != nullptr)
            cur->next = l1;
        else
            cur->next = l2;
        return temp.next;
    }
    
    ListNode* sortList(ListNode* head) {
        if (head == nullptr)
            return head;
        ListNode *slow = head, *fast = head;
        while (fast->next != nullptr && fast->next->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        ListNode *mid = slow->next;
        if (mid == nullptr)
            return head;
        slow->next = nullptr;
        ListNode *l1 = sortList(head);
        ListNode *l2 = sortList(mid);
        return merge(l1, l2);
    }

    然后是自底向上的非递归实现(分治思想):

    自底向上的方法实现起来有些难度,我使用了两个栈来存储中间链表,这种方法并不好,但我也想不出其他方法了

    在leetcode上测试发现比递归方法还要慢12ms,真是一次失败的优化。

    // Definition for singly-linked list.
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    
    ListNode *merge(ListNode *l1, ListNode *l2)
    {
        ListNode temp(0);
        ListNode *cur = &temp;
        while (l1 != nullptr && l2 != nullptr)
        {
            if (l1->val < l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        if (l1 != nullptr)
            cur->next = l1;
        else
            cur->next = l2;
        return temp.next;
    }
    
    ListNode* sortList(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return head;
        stack<ListNode*> s1;
        stack<ListNode*> s2;
        stack<ListNode*> *ps1 = &s1;
        stack<ListNode*> *ps2 = &s2;
        int cnt = 0;
        while (head != nullptr)
        {
            s1.push(head);
            ListNode *temp = head->next;
            head->next = nullptr;
            head = temp;
            cnt++;
        }
        if (cnt % 2 == 1) {
            ListNode *poped1 = s1.top();
            s1.pop();
            ListNode *poped2 = s1.top();
            s1.pop();
            s1.push(merge(poped1, poped2));
        }
            
        while (ps1->size() > 1) {
            int cnt = 0;
            while (!ps1->empty())
            {
                ListNode *l1 = ps1->top();
                ps1->pop();
                ListNode *l2 = ps1->top();
                ps1->pop();
                ps2->push(merge(l1, l2));
                cnt++;
            }
            if (cnt % 2 == 1 && cnt > 2) {
                ListNode *poped1 = ps2->top();
                ps2->pop();
                ListNode *poped2 = ps2->top();
                ps2->pop();
                ps2->push(merge(poped1, poped2));
            }
            stack<ListNode*> *temp = ps1;
            ps1 = ps2;
            ps2 = temp;
        }
        return ps1->top();
    }

    原来是自己想复杂了,不用使用栈来保存结点,下面是自底向上的正确解法

    /**
     * Merge sort use bottom-up policy, 
     * so Space Complexity is O(1)
     * Time Complexity is O(NlgN)
     * stable sort
    */
    class Solution {
    public:
        ListNode *sortList(ListNode *head) {
            if(!head || !(head->next)) return head;
    
            //get the linked list's length
            ListNode* cur = head;
            int length = 0;
            while(cur){
                length++;
                cur = cur->next;
            }
    
            ListNode dummy(0);
            dummy.next = head;
            ListNode *left, *right, *tail;
            for(int step = 1; step < length; step <<= 1){
                cur = dummy.next;
                tail = &dummy;
                while(cur){
                    left = cur;
                    right = split(left, step);
                    cur = split(right,step);
                    tail = merge(left, right, tail);
                }
            }
            return dummy.next;
        }
    private:
        /**
         * Divide the linked list into two lists,
         * while the first list contains first n ndoes
         * return the second list's head
         */
        ListNode* split(ListNode *head, int n){
            //if(!head) return NULL;
            for(int i = 1; head && i < n; i++) head = head->next;
    
            if(!head) return NULL;
            ListNode *second = head->next;
            head->next = NULL;
            return second;
        }
        /**
          * merge the two sorted linked list l1 and l2,
          * then append the merged sorted linked list to the node head
          * return the tail of the merged sorted linked list
         */
        ListNode* merge(ListNode* l1, ListNode* l2, ListNode* head){
            ListNode *cur = head;
            while(l1 && l2){
                if(l1->val > l2->val){
                    cur->next = l2;
                    cur = l2;
                    l2 = l2->next;
                }
                else{
                    cur->next = l1;
                    cur = l1;
                    l1 = l1->next;
                }
            }
            cur->next = (l1 ? l1 : l2);
            while(cur->next) cur = cur->next;
            return cur;
        }
    };

    后记:抽时间研究一下STL中的list::sort是如何实现的

  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/sdlwlxf/p/5070450.html
Copyright © 2011-2022 走看看