0023_Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

JAVA

方法一

可以把输入看做一个二维数组,数组的每一行都是递增的,因此每次只找第一列中最小的元素放入结果链表的尾部,然后将该行后续的数字前移。结果超时

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode result = new ListNode(0);
        ListNode tail = result;
        int min;
        int index;
        boolean empty = false;
        while(!empty){
            empty = true;
            min = Integer.MAX_VALUE;
            index = 0;
            for(int i = 0; i < lists.length; ++i){
                if(lists[i] != null){
                    empty = false;
                    if(lists[i].val <= min){
                        min = lists[i].val;
                        index = i;
                    }
                } 
            }
            if(!empty){
                tail.next = lists[index];
                tail = tail.next;
                lists[index] = lists[index].next;
            }
        }
        return result.next;
    }
}

方法二

超时的原因可能是在于每次选最小值的时候,都需要便利一次数组,假设共有M行N列,最坏情况下最小的元素总是出现在最后一列,那么时间复杂度将达到 O(MNM) 所以考虑建立一个小根堆,建堆时堆中包括第一列的全部元素并排序,之后每抛出一个最小的,就将最小元素的后一个元素入堆,若不存在则跳过。这样时间复杂度可以降到 O(MNlogM) 就是编码麻烦一些,尝试一下。
最开始没有考虑数组中有空节点的情况,后来加了次筛选,将初始为空的节点移动到数组尾部。另外代码中用last变量代表数组中最后一个非空节点的下标。提交后果然AC,效率在前20%。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode result = new ListNode(0);
        ListNode tail = result;
        int last = lists.length - 1;
        //将数组中的空节点移到尾部
        for(int i = 0; i <= last;){
            if (lists[i] == null){
                lists[i] = lists[last];
                lists[last] = null;
                --last;
            }else {
                ++i;
            }
        }
        //第一次建堆
        for(int i = (last-1)/2; i >= 0; --i){
            createHeap(lists,i,last);
        }
        while(last >= 0){
            tail.next = lists[0];
            tail = tail.next;
            if(lists[0].next != null){
                lists[0] = lists[0].next;
            }else{
                lists[0] = lists[last];
                lists[last] = null;
                --last;
            }
            //每次都从根节点(下标为0)开始调整堆
            createHeap(lists,0,last);
        }
        return result.next;
    }

    public void createHeap(ListNode[] lists,int target, int last){
        ListNode temp;
        int i = target;
        int j = i * 2 + 1;

        while(j >= 0 && j <= last){
            if(j < last && lists[j].val > lists[j+1].val){
                ++j;
            }
            if(lists[j].val < lists[i].val){
                temp = lists[j];
                lists[j] = lists[i];
                lists[i] = temp;
                i = j;
                j = i * 2 + 1;
            }else{
                break;
            }
        }
    }
}
To merge k sorted linked lists, one approach is to repeatedly merge two of the linked lists until all k lists have been merged into one. We can use a priority queue to keep track of the minimum element across all k linked lists at any given time. Here's the code to implement this idea: ``` struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; // Custom comparator for the priority queue struct CompareNode { bool operator()(const ListNode* node1, const ListNode* node2) const { return node1->val > node2->val; } }; ListNode* mergeKLists(vector<ListNode*>& lists) { priority_queue<ListNode*, vector<ListNode*>, CompareNode> pq; for (ListNode* list : lists) { if (list) { pq.push(list); } } ListNode* dummy = new ListNode(-1); ListNode* curr = dummy; while (!pq.empty()) { ListNode* node = pq.top(); pq.pop(); curr->next = node; curr = curr->next; if (node->next) { pq.push(node->next); } } return dummy->next; } ``` We start by initializing a priority queue with all the head nodes of the k linked lists. We use a custom comparator that compares the values of two nodes and returns true if the first node's value is less than the second node's value. We then create a dummy node to serve as the head of the merged linked list, and a current node to keep track of the last node in the merged linked list. We repeatedly pop the minimum node from the priority queue and append it to the merged linked list. If the popped node has a next node, we push it onto the priority queue. Once the priority queue is empty, we return the head of the merged linked list. Note that this implementation has a time complexity of O(n log k), where n is the total number of nodes across all k linked lists, and a space complexity of O(k).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值