欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Merge K Sorted List Leetcode #23 题解[C++]

程序员文章站 2022-06-03 10:37:51
...

题目来源


https://leetcode.com/problems/merge-k-sorted-lists/description/

题目描述


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个已经排好序的列表.

解题思路


有两种思路. 第一种是先写出耳熟能详的合并两个有序链表的函数, 再利用这个函数依次合并完所有的链表. 这是我一开始的思路, 但后来我想到了第二种思路, 便想试试第二种思路:

  1. 按照各链表的第一个元素, 先用快速排序把这些链表顺序排好;
  2. 第一个链表的第一个节点即是全局最小, 把它添加到结果链表中, 同时删除这个节点;
  3. 如果此时第一个链表已空, 删除这条链表, 后续的链表依次前移;
  4. 经过2,3之后, 此时第一条链表的第一个节点已经无法保证全局最小, 由于剩下的链表头结点都是排好了的, 用二分查找找出第一条链表的第一个节点所应放的正确位置, 直接把第一条链表移到该位置;
  5. 还有链表非空时, 重复2,3,4; 直至返回最终的合并链表.

复杂度分析

结合下面的代码, 假设n条长为m的链表, 第一次遍历去掉空链表是O(n), 之后一次快排是O(nlogn), 之后需要进行O(n*m)次操作把全部节点加入到最终链表中, 每一次都需要进行一次O(logn)的二分查找, 所以最终复杂度是O(nm log n).

比起来实际上第一种思路应该会快一些, 因为第二种思路实现的代码看起来速度相当一般. 如下图.

代码实现


class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        for (int count = 0; count < lists.size();) {
            if (lists[count] == nullptr) lists.erase(lists.begin() + count);
            else count++;
        }

        if (lists.empty()) return nullptr;

        ListNode combine(0);
        ListNode* last_sorted = &combine;

        quickSort(0, lists.size() - 1, lists);
        while (!lists.empty()) {
            last_sorted->next = lists[0];
            last_sorted = last_sorted->next;
            lists[0] = lists[0]->next;
            if (lists[0] == nullptr) {
                lists.erase(lists.begin());
                continue;
            }
            int idx = binarySearch(1, lists.size() - 1, lists[0]->val, lists);
            lists.insert(lists.begin() + idx, lists[0]);
            lists.erase(lists.begin());
        }

        return combine.next;

    }

    int binarySearch(int left, int right, int key, vector<ListNode*> & lists) {
        int lo = left;
        int hi = right;
        while (lo <= hi) {
            int mid = (lo + hi) / 2;
            if (key <= lists[mid]->val) {
                hi = mid - 1;
            }
            else lo = mid + 1;
        }
        return lo;
    }

    int partition(int left, int right, vector<ListNode*>& lists) {
        int lo = left;
        int hi = right;
        int pivot = lists[hi]->val;
        for (int k = lo; k < hi; k++) {
            if (lists[k]->val < pivot) {
                swap(lists[k], lists[lo++]);
            }
        }
        swap(lists[lo], lists[hi]);
        return lo;
    }

    void quickSort(int left, int right, vector<ListNode*>& lists) {
        if (left >= right) return;
        int idx = partition(left, right, lists);
        quickSort(left, idx - 1, lists);
        quickSort(idx + 1, right, lists);
    }
};

Merge K Sorted List Leetcode #23 题解[C++]

相关标签: Algorithm