lintcode-104. Merge K Sorted Lists

https://www.lintcode.com/problem/merge-k-sorted-lists/description

描述

合并k个排序链表,并且返回合并后的排序链表。尝试分析和描述其复杂度。

样例

给出3个排序链表 [2->4->null,null,-1->null],返回 -1->2->4->null

链表结构:

class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

方法一:

用 List< ListNode> nodeIs 容器保存当前所有链表的最小元素,比较他们中最小的节点加入所求列表中,该链表指向最小元素的指针后移,直到所有链表的指针都走到尾部。

使用该方法 通过 92% 后超时,设 链表有 n个,链表总长度为 m, 则时间复杂度为:O[n*m],

class Solution {
    /**
     * @param lists:
     *            a list of ListNode
     * @return: The head of one sorted list.
     */
    public ListNode mergeKLists(List<ListNode> lists) {
        if(lists==null||lists.size()==0){
            return null;
        }
        List<ListNode> nodeIs=new ArrayList<ListNode>();//存放所有链表指向当前最小元素的指针
        for(ListNode node:lists){
            if(node==null){//如果这个链表为空,就不分配指针了
                continue;
            }
            nodeIs.add(node);
        }
        ListNode resultHead=new ListNode(0);//定义所求链表的头指针
        ListNode p=resultHead; //需要移动的指针,始终指向链表的尾部

        int count=0; //走到头的链表数
        int n=nodeIs.size();//需要比较的链表条数     
        while(count<n){ //如果所有链表都走到头,说明构造结束
            ListNode minNode=nodeIs.get(0);//指向最小元素
            for(ListNode thisNode:nodeIs){
                if(minNode.val>thisNode.val){
                    minNode=thisNode;
                }
            }

            p.next=new ListNode(minNode.val);
            p=p.next;//所求的链表的尾指针后移
            nodeIs.remove(minNode); //移除原最小的元素  
            minNode=minNode.next;
            if(minNode==null){
                count++;
            }else{
                nodeIs.add(minNode);//将上一个最小元素,的下一个元素添加到最小指针集合中
            }
        }
        return resultHead.next;
    }
}

优化:可将需要比较的各个链表头元素构造成一个堆,这样在建堆之后,每次调整堆 需要的时间复杂度 为 logN,总体时间复杂度会降低为 O[ logN*m]。

class Solution {
    /**
     * @param lists:
     *            a list of ListNode
     * @return: The head of one sorted list.
     */
    public ListNode mergeKLists(List<ListNode> lists) {
        if(lists==null||lists.size()==0){
            return null;
        }
        List<ListNode> nodeIs=new ArrayList<ListNode>();//存放所有链表指向当前最小元素的指针
        for(ListNode node:lists){
            if(node==null){//如果这个链表为空,就不分配指针了
                continue;
            }
            nodeIs.add(node);
        }
        for(int i=nodeIs.size()-1;i>=0;--i){//从最后一个元素开始,向上调整
            adjustDown(nodeIs,i);
        }       
        ListNode resultHead=new ListNode(0);//定义所求链表的头指针
        ListNode p=resultHead; //需要移动的指针,始终指向链表的尾部
        while(nodeIs.size()>0){
            ListNode minNode=nodeIs.get(0);//堆顶元素,肯定为最小元素
            ListNode node=new ListNode(minNode.val);
            p.next=node;
            p=p.next;//p 向后移动
            nodeIs.remove(minNode);
            minNode=minNode.next;
            nodeIs.add(0, minNode);
            if(minNode==null){//如果当前链的下个元素为空,直接将堆的最后一个元素移动到堆顶
                Collections.swap(nodeIs, 0, nodeIs.size()-1);
                nodeIs.remove(nodeIs.size()-1);
            }
            if(nodeIs.size()>0){
                adjustDown(nodeIs, 0);
            }
        }
        return resultHead.next;
    }

    private void adjustDown(List<ListNode> nodeIs, int i) {//调整为最小堆
        int len=nodeIs.size();
        while(i<len){
            int left=i*2+1,right=i*2+2;
            int min_pos=i;
            if( (left<len) && (nodeIs.get(left).val < nodeIs.get(min_pos).val)){
                min_pos=left;
            }
            if( (right<len) && (nodeIs.get(right).val < nodeIs.get(min_pos).val)){
                min_pos=right;
            }
            if(min_pos!=i){
                Collections.swap(nodeIs, i, min_pos);
                i=min_pos;
            }else{
                break;
            }
        }

    }
}

使用优先队列,实现堆
Queue< ListNode> heap = new PriorityQueue< ListNode>(lists.size(), ListNodeComparator);

public class Solution {
    private Comparator<ListNode> ListNodeComparator = new Comparator<ListNode>() {
        public int compare(ListNode left, ListNode right) {
            return left.val - right.val;
        }
    };

    public ListNode mergeKLists(List<ListNode> lists) {
        if (lists == null || lists.size() == 0) {
            return null;
        }

        Queue<ListNode> heap = new PriorityQueue<ListNode>(lists.size(), ListNodeComparator);
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i) != null) {
                heap.add(lists.get(i));
            }
        }

        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        while (!heap.isEmpty()) {
            ListNode head = heap.poll();
            tail.next = head;
            tail = head;
            if (head.next != null) {
                heap.add(head.next);
            }
        }
        return dummy.next;
    }
}

方法四:
分治的思想,采用归并排序

public class Solution {
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    public ListNode mergeKLists(List<ListNode> lists) {
        if (lists.size() == 0) {
            return null;
        }
        return mergeHelper(lists, 0, lists.size() - 1);
    }

    private ListNode mergeHelper(List<ListNode> lists, int start, int end) {
        if (start == end) {
            return lists.get(start);
        }

        int mid = start + (end - start) / 2;
        ListNode left = mergeHelper(lists, start, mid);
        ListNode right = mergeHelper(lists, mid + 1, end);
        return mergeTwoLists(left, right);
    }

    private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                tail.next = list1;
                tail = list1;
                list1 = list1.next;
            } else {
                tail.next = list2;
                tail = list2;
                list2 = list2.next;
            }
        }
        if (list1 != null) {
            tail.next = list1;
        } else {
            tail.next = list2;
        }

        return dummy.next;
    }
}

猜你喜欢

转载自blog.csdn.net/zxm1306192988/article/details/80424575