【题解】合并k个已排序的链表

题目链接:合并k个已排序的链表

解题思路1:顺序遍历合并链表

代码如下:

    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        if (pHead1 == nullptr) return pHead2;
        if (pHead2 == nullptr) return pHead1;
        if (pHead1->val <= pHead2->val) {
            pHead1->next = Merge(pHead1->next, pHead2);
            return pHead1;
        } else {
            pHead2->next = Merge(pHead1, pHead2->next);
            return pHead2;
        }
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        //顺序遍历合并链表
        ListNode* res = nullptr;
        for (int i = 0; i < lists.size(); i++) {
            res = Merge(res, lists[i]);
        }
        return res;
    }

解题思路2:分治

将k个链表配对,将同一对链表合并,第一轮合并,k个链表将被合并得到k/2个链表,再接着是k/4个链表,k/8个链表等
重复合并的过程,最终我们得到了有序链表

代码如下:

    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        if (pHead1 == nullptr) return pHead2;
        if (pHead2 == nullptr) return pHead1;
        if (pHead1->val <= pHead2->val) {
            pHead1->next = Merge(pHead1->next, pHead2);
            return pHead1;
        } else {
            pHead2->next = Merge(pHead1, pHead2->next);
            return pHead2;
        }
    }
    ListNode* FZMerge(vector<ListNode*> &lists, int l, int r){
        if(l == r) return lists[l];
        if(l > r) return nullptr;
        int mid = (l + r) >> 1;
        return Merge(FZMerge(lists, l, mid), FZMerge(lists, mid+1, r));
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return FZMerge(lists, 0, lists.size()-1);
    }

解题思路3:利用小根堆,小根堆的堆顶元素是最小的,相当于我们一次找到了k个指针所指元素的最小值

首先构造一个比较链表节点大小的小根堆;
先遍历数组中k个链表的头部,将不是空节点的首个节点都加入到优先队列中去;
每次取出小根堆的堆顶元素,将该元素连接到合并后的链表后面,然后在该元素后一个节点不空的情况下,将该后一个节点放到堆中。

代码如下:

    struct cmp{
        //重载小根堆的比较方式
        bool operator()(ListNode* a, ListNode* b){
            return a->val > b->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        //小根堆
        priority_queue<ListNode*, vector<ListNode*>, cmp> pq;
        //将数组中每一个链表的首元素都放入小根堆中
        for(int i=0; i<lists.size(); i++){
            if(lists[i] != nullptr){
                pq.push(lists[i]);
            }
        }
        //虚拟头节点
        ListNode* res = new ListNode(-1);
        ListNode* head = res;
        while(!pq.empty()){
            //temp->利用小根堆堆顶元素最小
            ListNode* temp = pq.top();
            pq.pop();
            head->next = temp;
            head = head->next;
            //如果temp->next不空,则代表着该条链表没有遍历结束,将下一个元素放入堆中
            if(temp->next != nullptr){
                pq.push(temp->next);
            }
        }
        return res->next;
    }

你可能感兴趣的:(题目练习,链表,数据结构,算法)