zoukankan      html  css  js  c++  java
  • LeetCode(23) - Merge k Sorted Lists

      题目和LeetCode(21)里merge two sorted List要求差不多,现在只是从2两个list变成了k个list。

      看到这个题,第一个反应是用一个heap(最大堆)把k个list里面的数存起来,然后一个一个poll出来生成一个新的list。遍历所有list要O(n),再堆里面插入元素,需要O(log(n))的时间,再生成新的List需要O(n),所以平均时间为O(nlog(n) + n),

      代码如下:

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     public ListNode mergeKLists(ListNode[] lists) {
    11         ListNode dumpNode = new ListNode(0);
    12         Queue<Integer> heap = new PriorityQueue<Integer>();
    13         //把所有元素都放到heap里面。
    14         for (ListNode head : lists) {
    15             while (head != null) {
    16                 heap.offer(head.val);
    17                 head = head.next;
    18             }
    19         }
    20         ListNode curr = dumpNode;
    21         //生成新的list
    22         while (!heap.isEmpty()) {
    23             curr.next = new ListNode(heap.poll());
    24             curr = curr.next;
    25         }
    26         return dumpNode.next;
    27     }   
    28 }

      这样做其实非常简单,但是鉴于这道题是一道hard的题,我估计这样做并不能够得到面试官的认可。首先,它并没有利用到每个list sorted的这一个性质,第二个,时间上也可以有更快的方法。

      怎么做呢?那就是利用了归并排序的特点,divide and conquer(分治)。首先是把相邻的两个list两两配对,利用LeetCode 21 merge two sorted list的方法,分别把它们merge起来,然后继续两两配对,知道merge到一个list为止。

      代码如下:

     1 /**
     2  * Definition for singly-linked list.
     3  * public class ListNode {
     4  *     int val;
     5  *     ListNode next;
     6  *     ListNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     public ListNode mergeKLists(ListNode[] lists) {
    11         ListNode res = mergeKListsHelper(lists,0,lists.length - 1);
    12         return res;
    13     }
    14     
    15     private ListNode mergeKListsHelper(ListNode[] lists, int left, int right) {
    16         //返回条件的三种情况。
    17         if (left > right) return null;
    18         //没有配对上的list
    19         if (left == right) return lists[left];
    20         //当left和right相差一个时,把它们merge起来。
    21         if (left + 1 == right) return mergeSortedList(lists[left],lists[right]);
    22         //分治,对于每一堆list,中间分开,左右各自合并,最后再merge
    23         int mid = (left + right) / 2;
    24         ListNode leftNode = mergeKListsHelper(lists, left, mid-1);
    25         ListNode rightNode = mergeKListsHelper(lists, mid, right);
    26         return mergeSortedList(leftNode, rightNode);
    27     }
    28     
    29     //merge两个list。和Leetcode 21一样。
    30     private ListNode mergeSortedList(ListNode l1, ListNode l2) {
    31         ListNode dumpNode = new ListNode(0);
    32         ListNode curr = dumpNode;
    33         while (l1 != null && l2 != null) {
    34             if (l1.val < l2.val) {
    35                 curr.next = new ListNode(l1.val);
    36                 l1 = l1.next;
    37             }
    38             else {
    39                 curr.next = new ListNode(l2.val);
    40                 l2 = l2.next;
    41             }
    42             curr = curr.next;
    43         }
    44         
    45         while (l1 != null) {
    46             curr.next = new ListNode(l1.val);
    47             l1 = l1.next;
    48             curr = curr.next;
    49         }
    50         
    51         while (l2 != null) {
    52             curr.next = new ListNode(l2.val);
    53             l2 = l2.next;
    54             curr = curr.next;
    55         }
    56         
    57         return dumpNode.next;
    58     }
    59 }
  • 相关阅读:
    noip2016组合数问题
    noip2017奶酪
    洛谷1091合唱队形
    洛谷P1075 质因数分解
    洛谷1004方格取数
    POJ2393奶酪工厂
    NOIP2012国王游戏(60分题解)
    洛谷1106删数问题
    洛谷1209修理牛棚
    二维树状数组区间修改+区间查询模版
  • 原文地址:https://www.cnblogs.com/kepuCS/p/5278633.html
Copyright © 2011-2022 走看看