c++ - 合并 k 个排序列表超出时间限制(leetcode)

标签 c++ algorithm sorting

merge-k-sorted-lists

合并 k 个排序链表并将其作为一个排序列表返回。分析并描述其复杂性。

我的代码:

    ListNode *mergeTwoLists(ListNode *p1, ListNode *p2) {
    ListNode dummy(-1);
    ListNode *head = &dummy;
    while(p1 != nullptr && p2 != nullptr) {
        if (p1->val < p2->val) {
            head->next = p1;
            head = head->next;
            p1 = p1->next;
        } else {
            head->next = p2;
            head = head->next;
            p2 = p2->next;
        }
    }
    if (p1 != nullptr) {
        head->next = p1;
    }
    if (p2 != nullptr) {
        head->next = p2;
    }
    //head->next = nullptr;
    return dummy.next;
}
ListNode *mergeKLists(vector<ListNode *> &lists) {
    if (lists.size() == 0) return nullptr;
    if (lists.size() == 1) return lists[0];
    ListNode *p1, *p2, *p;
    while (lists.size() > 1) {
        p1 = lists.back();
        lists.pop_back();
        p2 = lists.back();
        lists.pop_back();
        p = mergeTwoLists(p1, p2);
        lists.push_back(p);
    }
    return lists[0];
}

我总是超出时间限制。我该如何更改程序?

最佳答案

您所做的事情具有复杂性O(nk^2),其中n是每个数组的大小。您一次合并两个列表。为什么 ?合并前两个列表需要 2n 次操作,前两个列表合并后的大小为 2n。现在将其与第三个合并,数组大小变为 3n 并且完成 3n 操作,因此操作总数为 2n+3n+....kn (算术级数),即O(nk^2)。相反,采用优先级队列(最小堆)插入所有 k 列表的第一个元素。现在,每次从优先级队列中取出最小的元素(将其放入新列表中),将其从优先级队列中删除并插入该元素所属列表的下一个元素。由于所有元素都从优先级队列中插入和删除一次,总共有 nk 个元素,因此复杂度为 O(nklog(k))。 (删除/插入的时间)优先级队列是O(log(number_of_elements_in_queue))。并且队列中任何时候最多有 k 个元素。
有关更详细的解释和代码,请查看此处:Merging k sorted lists 。我认为这足以在 leetcode 上获得 AC :)。

关于c++ - 合并 k 个排序列表超出时间限制(leetcode),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28935642/

相关文章:

c++ - 完美转发类模板参数推导

algorithm - 波束搜索算法中的波束大小代表什么?

根据哈希表的条目值(而不是键)对哈希表进行排序

java - 星算法不起作用

c - C中的排序结构无法在VS2017中显示输出结果,但在CodeBlocks中显示

arrays - swift 4 : Sorting an Array by 3 Conditions

c++ - 如何存储由 std::unique_ptr 给出的抽象类对象的 vector ?

c++ - VC6编译错误

java - 什么是 Java cyclicbarrier 的 C++ 版本?

java - 使用 1 个数组实现 3 个堆栈,此代码是否有效?