Leetcode: 23.Merge k Sorted Lists

Leetcode: 23.Merge k Sorted Lists

題目一目瞭然就是要對k個已經排序了的list進行合併排序,最後返回一個合併好的序列。

priority queue

將每個list的最小節點放入一個priority queue (min heap)中。之後每從queue中取出一個節點,則將該節點在其list中的下一個節點插入,以此類推直到全部節點都經過priority queue。由於priority queue的大小爲始終爲k,而每次插入的複雜度是log k,一共插入過nk個節點。時間複雜度爲O(nk logk),空間複雜度爲O(k)

注意C++的STL中的priority queue默認是max heap,需要定義一個新的比較函數。

class Solution {
public:
    struct compNode {
        bool operator()(ListNode *p, ListNode *q) const {
            return p->val>q->val;
        }  
    };

    ListNode *mergeKLists(vector<ListNode *> &lists) {
        priority_queue<ListNode*, vector<ListNode*>, compNode> pq;
        ListNode *dummy = new ListNode(0), *tail = dummy;

        for(int i=0; i<lists.size(); i++) 
            if(lists[i]) pq.push(lists[i]);

        while(!pq.empty()) {
            tail->next = pq.top();
            tail = tail->next;
            pq.pop();
            if(tail->next) pq.push(tail->next);
        }

        return dummy->next;
    }
};

Merge two lists

利用合併兩個list的方法,依次將每個list合併到結果的list中。這個方法的空間複雜度爲O(1),時間複雜度爲:
2n + 3n + ... + kn = [(k+1)*k/2-1]*n = O(nk^2)

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        ListNode *ret = NULL;
        for(int i=0; i<lists.size(); i++) 
            ret = merge2Lists(ret, lists[i]);
        return ret;
    }

    ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
        ListNode *dummy = new ListNode(0), *tail = dummy;
        while(h1 && h2) {
            if(h1->val<=h2->val) {
                tail->next = h1;
                h1 = h1->next;
            }
            else {
                tail->next = h2;
                h2 = h2->next;
            }
            tail = tail->next;
        }
        tail->next = h1 ? h1 : h2;
        return dummy->next;
    }
};

二分法

類似merge sort,每次將所有的list兩兩之間合併,直到所有list合併成一個。如果用迭代而非遞歸,則空間複雜度爲O(1)。時間複雜度:
2n * k/2 + 4n * k/4 + ... + (2^x)n * k/(2^x) = nk * x
k/(2^x) = 1 -> 2^x = k -> x = log2(k)

所以時間複雜度爲O(nk log(k)),與方法一相同。

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        if(lists.empty()) return NULL;
        int end = lists.size()-1;
        while(end>0) {
            int begin = 0;
            while(begin<end) {
                lists[begin] = merge2Lists(lists[begin], lists[end]);
                begin++;
                end--;
            }
        }
        return lists[0];
    }

    ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
        ListNode *dummy = new ListNode(0), *tail = dummy;
        while(h1 && h2) {
            if(h1->val<=h2->val) {
                tail->next = h1;
                h1 = h1->next;
            }
            else {
                tail->next = h2;
                h2 = h2->next;
            }
            tail = tail->next;
        }
        tail->next = h1 ? h1 : h2;
        return dummy->next;
    }
};

粗暴法

直接把所有節點push進一個vector,然後sort一下,重新串起來就好了,時間複雜度爲O(nk log(nk)),也能過……就是這樣粗暴。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章