zoukankan      html  css  js  c++  java
  • lintcode104

    Merge k sorted linked lists and return it as one sorted list.
    Analyze and describe its complexity.
    Example
    Given lists:
    [
    2->4->null,
    null,
    -1->null
    ],
    return -1->2->4->null.

    O(nLogk)时间复杂度。三种做法都要会。


    1.维护最小堆。每个链表已经排序了,头相当于帮派最强者,每次要选出各帮派此时最强者,那只要比所有列表头即可,想到用堆。初始化把所有头扔进去,while循环堆没空,就把当前最强者当整体排序链表的下一个;检查一下刚才poll出来的下一位是不是null,不是null的话继续放到堆里。

    2.分治法,自顶向下,递归。
    函数private ListNode merge2List(ListNode head1, ListNode head2)负责把两条ListNode链合在一起,函数private ListNode mergeHelper(List<ListNode> lists, int start, int end)负责分别叫左右都合成一条,再把这两条合好传回去。递归出口是只有一条的时候返回自己。顶上一层层分配任务下去给两边。

    3.自底向上,遍历非递归。
    还是先写一个合两条的方法。每次两条两条合并,比如12345678就12,34,56,78合合,接着下一轮两两合并,直到最后只剩下一条返回。可以感受到是从底下慢慢向上只剩一条吧。不过这个方法注意写隔两个隔两个合并的部分的时候,记得for循环+=2!!别手快写错,一开始只+1死循环找错好久。

    实现1: 维护最小堆。

    /**
     * Definition for ListNode.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int val) {
     *         this.val = val;
     *         this.next = null;
     *     }
     * }
     */ 
    public class Solution {
        /**
         * @param lists: a list of ListNode
         * @return: The head of one sorted list.
         */
        public ListNode mergeKLists(List<ListNode> lists) {  
            // write your code here
            
            if (lists == null || lists.size() == 0) {
                return null;
            }
            
            int k = lists.size();
            PriorityQueue<ListNode> minHeap = new PriorityQueue<>(k, new Comparator<ListNode>() {
                @Override
                public int compare(ListNode n1, ListNode n2) {
                    return n1.val - n2.val;
                }
            });
            
            for (int i = 0; i < k; i++) {
                if (lists.get(i) != null) {
                    minHeap.offer(lists.get(i));
                }
            }
            
            ListNode dummy = new ListNode(-1);
            ListNode crt = dummy;
            while (!minHeap.isEmpty()) {
                ListNode minNode = minHeap.poll();
                crt.next = minNode;
                crt = crt.next;
                if (minNode.next != null) {
                    minHeap.offer(minNode.next);
                }
            }
            return dummy.next;
        }
    }

    实现2: 分治法,自顶向下,递归。

    /**
     * Definition for ListNode.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int val) {
     *         this.val = val;
     *         this.next = null;
     *     }
     * }
     */ 
    public class Solution {
        /**
         * @param lists: a list of ListNode
         * @return: The head of one sorted list.
         */
        public ListNode mergeKLists(List<ListNode> lists) {  
            // write your code here
            if (lists == null || 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 leftResult = mergeHelper(lists, start, mid);
            ListNode rightResult = mergeHelper(lists, mid + 1, end);
            return merge2List(leftResult, rightResult);
        }
        
        private ListNode merge2List(ListNode head1, ListNode head2) {
            ListNode dummy = new ListNode(-1);
            ListNode crt = dummy;
            while (head1 != null || head2 != null) {
                if (head2 == null) {
                    crt.next = head1;
                    head1 = head1.next;
                } else if (head1 == null) {
                    crt.next = head2;
                    head2 = head2.next;
                } else if (head1.val < head2.val) {
                    crt.next = head1;
                    head1 = head1.next;
                } else {
                    crt.next = head2;
                    head2 = head2.next;
                }
                crt = crt.next;
            }
            return dummy.next;
        }
    }

    实现3: 自底向上,遍历非递归。

    /**
     * Definition for ListNode.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int val) {
     *         this.val = val;
     *         this.next = null;
     *     }
     * }
     */ 
    public class Solution {
        /**
         * @param lists: a list of ListNode
         * @return: The head of one sorted list.
         */
        public ListNode mergeKLists(List<ListNode> lists) {  
            // write your code here
            if (lists == null || lists.size() == 0) {
                return null;
            }
            
            List<ListNode> crtLists = lists;
            while (crtLists.size() > 1) {
                List<ListNode> newLists = new ArrayList<>();
                // 千万注意这里是+=2!!!不然就死循环而且逻辑错误了!!!别手快
                for (int i = 0; i < crtLists.size(); i += 2) {
                    if (i + 1 == crtLists.size()) {
                        newLists.add(crtLists.get(i));
                    } else {
                        newLists.add(merge2List(crtLists.get(i), crtLists.get(i + 1)));
                    }
                }
                crtLists = newLists;
                System.out.println("1");
            }
            return crtLists.get(0);
        }
        
        private ListNode merge2List(ListNode head1, ListNode head2) {
            ListNode dummy = new ListNode(-1);
            ListNode crt = dummy;
            while (head1 != null || head2 != null) {
                if (head2 == null) {
                    crt.next = head1;
                    head1 = head1.next;
                } else if (head1 == null) {
                    crt.next = head2;
                    head2 = head2.next;
                } else if (head1.val < head2.val) {
                    crt.next = head1;
                    head1 = head1.next;
                } else {
                    crt.next = head2;
                    head2 = head2.next;
                }
                crt = crt.next;
                System.out.println("2");
            }
            return dummy.next;
        }
    }
  • 相关阅读:
    编写高性能Web应用程序的10个入门技巧
    C#中class与struct的区别[转]
    web架构设计经验分享 (转)
    NUnit入门篇
    sqlserver 重建日志文件
    ExecuteReader如何取得输出参数和返回值
    防止表单重复提交的几种方案
    Web 2.0 versus Virtual Worlds (转)
    ActionScript 3.0 Step By Step系列(七):使用XML和XMLList类处理XML数据 (转)
    PlayButton Component
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9596036.html
Copyright © 2011-2022 走看看