• 【LeetCode-链表】合并K个排序链表


    题目描述

    合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
    示例:

    输入:
    [
      1->4->5,
      1->3->4,
      2->6
    ]
    输出: 1->1->2->3->4->4->5->6
    

    题目链接: https://leetcode-cn.com/problems/merge-k-sorted-lists/

    思路1

    使用优先队列也就是小根堆来做。队列中的元素类型为pair<ListNode*>,这里需要自定义比较函数将 ListNode* 按值从小到大排在优先队列中,值小的在队头,值大的在队尾。首先将每个链表的链表头入队(如果不空的话)。然后弹出队头元素,将队头元素加入到新链表中,将队头元素的下一个元素加入到队列中(如果不为空)。这样循环,直到队列为空。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    struct Compare{
        bool operator()(ListNode* p1, ListNode* p2){
            return p1->val > p2->val;
        }
    };
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            if(lists.empty()) return nullptr;
    
            priority_queue<ListNode*, vector<ListNode*>, Compare> q;
            for(ListNode* list:lists){
                if(list!=nullptr) q.push(list);
            }
    
            ListNode* head = new ListNode(0);
            ListNode* curNode = head;
            while(!q.empty()){
                auto node = q.top(); q.pop();
                curNode->next = node; 
                curNode = curNode->next;
                if(node->next!=nullptr) q.push(node->next);
            }
            return head->next;
        }
    };
    

    这里需要注意比较函数的写法。

    • 时间复杂度:O(nk)
    • 空间复杂度:O(n)

    思路2

    使用合并两个有序链表中的方法逐个合并链表。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    struct Compare{
        bool operator()(ListNode* p1, ListNode* p2){
            return p1->val > p2->val;
        }
    };
    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {  // 合并两个链表
            if(l1==nullptr) return l2;
            if(l2==nullptr) return l1;
    
            ListNode* head = new ListNode(0);
            ListNode* curNode = head;
            while(l1 && l2){
                if(l1->val < l2->val){
                    curNode->next = l1;
                    l1 = l1->next;
                }else{
                    curNode->next = l2;
                    l2 = l2->next;
                }
                curNode = curNode->next;
            }
            if(l1==nullptr) curNode->next = l2;
            if(l2==nullptr) curNode->next = l1;
            return head->next;
        }
    
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            if(lists.empty()) return nullptr;
    
            ListNode* head = nullptr;
            for(auto list:lists){
                head = mergeTwoLists(head, list);
            }
            return head;
        }
    };
    
    • 时间复杂度:O(nk)
    • 空间复杂度:O(1)

    思路3

    使用类似归并排序的思想。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            if(lists.empty()) return nullptr;
    
            return mergeSort(lists, 0, lists.size()-1);
        }
    
        ListNode* mergeSort(vector<ListNode*> lists, int left, int right){
            if(left==right) return lists[left];
    
            int mid = left + (right-left)/2;
            ListNode* list1 = mergeSort(lists, left, mid);
            ListNode* list2 =  mergeSort(lists, mid+1, right);
            return mergeTwoList(list1, list2);
        }
    
        ListNode* mergeTwoList(ListNode* list1, ListNode* list2){
            if(list1==nullptr) return list2;
            if(list2==nullptr) return list1;
    
            ListNode* dummy = new ListNode(0);
            ListNode* cur = dummy;
            while(list1!=nullptr && list2!=nullptr){
                if(list1->val<list2->val){
                    cur->next = list1;
                    list1 = list1->next;
                }else{
                    cur->next = list2;
                    list2 = list2->next;
                }
                cur = cur->next;
            }
            if(list1!=nullptr) cur->next = list1;
            if(list2!=nullptr) cur->next = list2;
    
            return dummy->next;
        }
    };
    
  • 相关阅读:
    数据结构之 线性表 逆序简历链表
    数据结构之 线性表--顺序创建链表
    参观——校园招聘大会
    SDUT OJ 之 1571 《人品,有没有?》 字符串的处理问题
    青岛理工交流赛 H题 素数间隙
    青岛理工ACM交流赛 J题 数格子算面积
    STL版 括号匹配(感觉不如之前自己用数组模拟的跑的快)
    1076: [SCOI2008]奖励关( dp )
    BZOJ 1079: [SCOI2008]着色方案( dp )
    BZOJ 1984: 月下“毛景树”( 树链剖分 )
  • 原文地址:https://www.cnblogs.com/flix/p/13062514.html
Copyright © 2020-2023  润新知