0023_Merge k Sorted Lists

来源:互联网 发布:三菱fx2n 4da编程实例 编辑:程序博客网 时间:2024/06/07 09:15

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