LeetCode-23. 合并 K 个升序链表

问题分析

  1. 先建立一个小顶堆
  2. 将每一路的最小元素都加入小顶堆,此时堆顶元素就是全局的最小值
  3. 将堆顶元素弹出。若堆顶元素所在的数组不为空,则将下一元素加入堆中
  4. 重复2、3操作,直到所有数据都读取完毕
  5. 将堆内元素按顺序读出,并清空堆内元素

复杂度分析

建堆操作的时间复杂度: O ( l o g k ) O(logk) O(logk)

  • 递归式: T ( k ) = 2 T ( k / 2 ) + l o g n T(k) = 2T(k/2) + logn T(k)=2T(k/2)+logn,可以用主定理得出上述建堆操作的时间复杂度

单次插入操作的时间复杂度: O ( l o g k ) O(logk) O(logk)

返回堆顶元素的时间复杂度: O ( 1 ) O(1) O(1)

删除堆顶元素的时间复杂度: O ( l o g k ) O(logk) O(logk)

整体的时间复杂度: O ( n l o g k ) O(nlogk) O(nlogk)

程序代码

/**
 * 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* mergeKLists(vector<ListNode*>& lists) {
        // 最小堆
        auto cmp = [](const ListNode* A, const ListNode* B) {
	        return A -> val > B -> val;
        };
        priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> q;
        // 初始化小顶堆
        for(int i = 0; i < lists.size(); i++) {
            if( lists[i] )  q.push(lists[i]);
        }
        ListNode* dummy = new ListNode();
        ListNode* head = dummy;
        while( !q.empty() ) {
            auto node = q.top();
            q.pop();
            head -> next = node;
            if( node -> next ) {
                node = node -> next;
                q.push(node);
            }
            head = head -> next;
        }
        return dummy -> next;
    }
};

你可能感兴趣的:(leetcode题解,leetcode,链表,算法)