【leetcode】【hard】23. Merge k Sorted Lists

23. Merge k Sorted Lists

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

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

思路

很容易想到的有2种方法:

1.所有元素逐个压入优先队列,再逐个输出。

2.所有vector两两合并。

下面对两个方法逐个分析。

法一:优先队列

运行结果:结果正确但超时。

仔细分析:链表是有序的,所以链表的头节点的大小代表了整个链表的最小值,因此如果后面的链都小于前面的链,那么队列就需要频繁调整。

改进:先插入所有头节点,取出时判断被取节点后面是否还有节点,有则继续入队。这样可以保证每次优先对头节点最小的链表进行整理,维护的队列大小从n减小到k,从而运行速度也减小。

时间复杂度O(nlogk),空间复杂度O(k)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    struct cmp{
        bool operator()(ListNode* n1, ListNode* n2){
            return n1->val > n2->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size()<=0) return NULL;
        if(lists.size()==1) return lists[0];
        priority_queue<ListNode* ,vector<ListNode*> , cmp> pq;
        for(int i=0; i<lists.size(); ++i){
            ListNode* head = lists[i];
            if(head) pq.push(head);
        }
        ListNode* node = new ListNode(INT_MIN);
        auto idx = node;
        while(!pq.empty()){
            auto top = pq.top();
            idx->next = top;
            idx = idx->next;
            pq.pop();
            if(top->next) pq.push(top->next);
        }
        return node->next;
    }
};

法二:两两合并

取第一个链表当作基础链表,后面的链表不断向内插入。

缺点:当每个链表中元素的大小很均匀时,链表长度越来越长,插入时间也越来越长(元素会重复遍历多遍)。

/**
 * 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.size()<=0) return NULL;
        if(lists.size()==1) return lists[0];
        ListNode* node = new ListNode(0);
        auto head1 = lists[0];
        node->next = head1;
        for(int i=1; i<lists.size(); ++i){
            head1 = node;
            auto head2 = lists[i];
            while(head1->next && head2){
                if(head1->next->val > head2->val){
                    auto tmp = head1->next;
                    head1->next = head2;
                    head2 = head2->next;
                    head1 = head1->next;
                    head1->next = tmp;
                }else head1 = head1->next;
            }
            if(head2) head1->next = head2;
        }
        return node->next;
    }
};

优化:在实现逻辑上,链表两两合并,再不断向上两两合并。可通过链表队列实现。

代码来源:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/23-he-bing-kge-pai-xu-lian-biao-yi-bu-bu-you-hua-d/

/**
 * 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) {
        int size = lists.size();
        if (size == 0) {
            return nullptr;
        }
        if (size == 1) {
            return lists[0];
        }
        queue<ListNode*> waiting(deque<ListNode*>(lists.begin(), lists.end())); //将vector转为队列
        //如果队列元素大于1,则取出两个进行合并,合并后的链表继续添加到链表尾部
        while (waiting.size() > 1) {
            ListNode *l1 = waiting.front();
            waiting.pop();
            ListNode *l2 = waiting.front();
            waiting.pop();
            waiting.push(merge2(l1, l2));
        } 
        return waiting.front();
    }
    ListNode* merge2(ListNode *l1, ListNode *l2) {
        ListNode *head = new ListNode(0);
        ListNode *p = head;
        while (l1 && l2) {
            if (l1->val < l2->val) {
                p->next = l1;
                l1 = l1->next;
            } else {
                p->next = l2;
                l2 = l2->next;
            }
            p = p->next;
        }
        p->next = l1 ? l1 : l2;
        return head->next;
    }
};

发布了127 篇原创文章 · 获赞 2 · 访问量 3754

猜你喜欢

转载自blog.csdn.net/lemonade13/article/details/104374192