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

22 篇文章 0 订阅
18 篇文章 0 订阅

题目来源


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);
    }
};

ac_7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值