LeetCode 23. Merge k Sorted Lists

原題

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6

思路

拍腦門算法

合併k個有序鏈表,假設每個鏈表中的元素個數最多爲n,那麼總共的元素個數爲kn個,拍腦門算法可以將每個鏈表頭結點值進行k-1次比較,得到最小的元素放到新的鏈表裏,總共比較次數爲kn,時間複雜度爲O(k2n)O(k^2n)

歸併排序

一般出現排序的題目,時間複雜度要儘可能降爲O(nlogn)O(nlogn)或者O(n)O(n),而一出現loglog,就要往二叉樹上靠,這裏可以使用分治法來解決這個問題。

對k個有序鏈表進行兩兩排序,然後對排序結果再進行兩兩排序,重複此步驟,直到最後合成一個鏈表。
在這裏插入圖片描述
如上圖,總共有k個鏈表,那麼上面二叉數的層高爲log(k)log(k),每層需要比較的元素個數均爲knkn(即所有的元素都要進行一次比較),那麼總的時間複雜度爲O(knlog(k))O(knlog(k))

代碼

class Solution {
public:
	//假設lists中的(l, m), (m+1, r)區間已經完成合並,並且合併的鏈表頭結點在lists[l],lists[m+1]
	//然後合併lists[l],lists[m+1]兩個鏈表,並將頭結點賦予lists[l])(即最左邊的索引)
    void merge(vector<ListNode*> &lists, int l, int m, int r) {

        ListNode *p = lists[l], *q = lists[m+1];
        ListNode *new_list = NULL, *head = NULL;
		//判斷兩個鏈表是否爲空
        if (q == NULL) return ;

        if (p == NULL) {
            lists[l] = q;
            return ;
        }

        new_list = new ListNode(-1);
        head = new_list;

        while (p != NULL && q != NULL)
        {
            if (q->val < p->val)
            {
                new_list->next = new ListNode(q->val);
                q = q->next;
            }
            else
            {
                new_list->next = new ListNode(p->val);
                p = p->next;
            }
            new_list = new_list->next;
        }

        if(p == NULL)
        	new_list->next = q;
        if(q == NULL)
            new_list->next = p;
        lists[l] = head->next;
    }
	//分治法
	//將lists分爲(l, m), (m+1, r)兩個部分,分別進行合併,並將合併好的鏈表頭結點賦予lists[l], lists[m+1](即最左邊的索引)
	//合併lists(l), lists[m+1]
    void divide_conquer(vector<ListNode*> &lists, int l, int r) {
        if (l < r) {
            int m = (l+r)/2;
            divide_conquer(lists, l, m);
            divide_conquer(lists, m+1, r);
            merge(lists, l, m, r);
        }
    }
	//返回最左邊索引的頭結點
    ListNode* mergeKLists(vector<ListNode*>& lists)
    {
        if (lists.size() == 0)
            return NULL;
        divide_conquer(lists, 0, lists.size() - 1);
        return lists[0];
    }
};

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