• [leetcode]Merge k Sorted Lists


    Merge k Sorted Lists

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

    这道题,第一次刷是过了,第二次同样的代码超时了,看来case是在不断加强的

    算法

    思路1:

    最土的算法,两个月前能过,现在TLE,同[leetcode]Merge Two Sorted Lists

    首先把l1和l2合并到l1中,遍历2n个节点

    再把合并之后的l1和l3合并到l1中,遍历3n个节点

    再把合并之后的l1和l4合并到l1中,遍历4n个节点

    ....

    最后把合并后的l1和lm合并到l1中,遍历m*n个节点

    总共遍历了(2+3+...+m)*n个节点,时间复杂度为O(n*m^2)

    代码如下:

     1   public ListNode mergeKLists(List<ListNode> lists) {
     2         if(lists == null || lists.size() == 0) return null;
     3         ListNode l1 = lists.get(0);
     4         for(int i = 1; i < lists.size(); i++)
     5             l1 = mergeTwoLists(l1,lists.get(i));
     6         return l1;
     7     }
     8     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     9         if(l1 == null) return l2;
    10         if(l2 == null) return l1;
    11         ListNode head = new ListNode(1);
    12         head.next = l1;
    13         ListNode pre = head;
    14         ListNode node = l2;
    15         while(l2 != null){
    16             node = l2;
    17             while(pre.next != null && pre.next.val <= node.val){
    18                 pre = pre.next;
    19             }
    20             l2 = node.next;
    21             node.next = pre.next;
    22             pre.next = node;
    23             pre = node;
    24         }
    25         return head.next;
    26     }
    View Code

    思路2:

    分治法,将m个list分成两拨list1,list2,对每一拨分别处理

    当list.size() = 1时,直接返回, size() = 2时候,即:merge2ListNode

    处理完list1 和list2之后,再把二者合并

    时间负责度O(n*klogk)【其中k为list.size()】

    代码如下:

     1 public class Solution {
     2     public ListNode mergeKLists(List<ListNode> lists) {
     3         if(lists == null || lists.size() == 0) return null;
     4         if(lists.size() == 1) return lists.get(0);
     5         if(lists.size() == 2){
     6             return merge2List(lists.get(0), lists.get(1));
     7         }
     8         List<ListNode> l1 = new ArrayList<ListNode>();
     9         List<ListNode> l2 = new ArrayList<ListNode>();
    10         for(int i = 0;i < lists.size() ; i++){
    11             if(i < lists.size() / 2) l1.add(lists.get(i));
    12             else l2.add(lists.get(i));
    13         }
    14         ListNode list1 = mergeKLists(l1);
    15         ListNode list2 = mergeKLists(l2);
    16         return merge2List(list1, list2);
    17     }
    18     private ListNode merge2List(ListNode l1,ListNode l2){
    19         ListNode head = new ListNode(1);
    20         head.next = l1;
    21         ListNode pre = head;
    22         ListNode node = l2;
    23         while(l2 != null){
    24             node = l2;
    25             while(pre.next != null && pre.next.val <= node.val){
    26                 pre = pre.next;
    27             }
    28             l2 = node.next;
    29             node.next = pre.next;
    30             pre.next = node;
    31             pre = node;
    32         }
    33         return head.next;
    34     }
    35 }
    View Code

    思路3:

    堆,由于对堆不熟悉,所以写出来的代码很丑,不过好歹AC了,时间复杂度同分治法,明天过来再优化一下:

    渣代码如下:

     1 public class Solution {
     2     public ListNode mergeKLists(List<ListNode> lists) {
     3         if(lists == null || lists.size() == 0) return null;
     4         int k = 0;
     5         List<ListNode> list = new ArrayList<ListNode>();
     6         for(int i = 0; i < lists.size(); i++){
     7             if(lists.get(i) != null) {
     8                 k++;
     9                 list.add(lists.get(i));
    10             }
    11         }
    12         if(k == 0) return null;
    13         if(k == 1) return list.get(0);
    14         ListNode[] heap = new ListNode[k];
    15         for(int i = 0 ; i < k ; heap[i] = list.get(i),i++);
    16         for(int i = k / 2  - 1; i >= 0; i--){
    17             adjustHeap(heap, k, i);
    18         }
    19         ListNode result = new ListNode(0);
    20         ListNode tail = result;
    21         while(true){
    22             if(heap[0] == null){
    23                 heap[0] = heap[k - 1];
    24                 k--;
    25             }
    26             adjustHeap(heap, k, 0);
    27             tail.next = heap[0];
    28             if(k == 0) break;
    29             heap[0] = heap[0].next;
    30             tail = tail.next;
    31         }
    32         return result.next;
    33     }
    34     private void adjustHeap(ListNode[] heap,int size,int i){
    35         while( 2 * i + 1 < size ){
    36             ListNode left = heap[2 * i + 1];
    37             if(left == null) return;
    38             if(2 * i + 2 < size){
    39                 ListNode right = heap[2 * i + 2];
    40                 if(right.val <= left.val && right.val < heap[i].val){
    41                     ListNode tem = right;
    42                     heap[2 * i + 2] = heap[i];
    43                     heap[i] = tem;
    44                     i = 2 * i + 2;
    45                 }else if(left.val <= right.val && left.val < heap[i].val){
    46                     ListNode tem = left;
    47                     heap[2 * i + 1] = heap[i];
    48                     heap[i] = tem;
    49                     i = 2 * i + 1;
    50                 }else return;
    51             }else{
    52                 if(left.val < heap[i].val){
    53                     ListNode tem = left;
    54                     heap[2 * i + 1] = heap[i];
    55                     heap[i] = tem;
    56                 }
    57                 return;
    58             }
    59         }
    60     }
    61     
    62 }
    View Code

    第二遍:

     使用PriorityQueue的算法更简单一点,不过需要注意要定义比较器

    代码如下:

     1 public class Solution {
     2     public ListNode mergeKLists(List<ListNode> lists) {
     3         if(lists == null || lists.size() == 0) return null;
     4         Queue<ListNode> pq = new PriorityQueue<ListNode>(20,new Comparator<ListNode>(){
     5             @Override
     6             public int compare(ListNode a,ListNode b){
     7                 return a.val - b.val;
     8             }
     9         });
    10         ListNode newHead = new ListNode(0);
    11         ListNode tail = newHead;
    12         for(ListNode head : lists){
    13             if(head != null) pq.offer(head);
    14         }
    15         while(!pq.isEmpty()){
    16             ListNode node = pq.poll();
    17             tail.next = node;
    18             if(node.next != null) pq.offer(node.next);
    19             node.next = null;
    20             tail = node;
    21         }
    22         return newHead.next;
    23     }
    24 }
    View Code

    参考资料:

  • 相关阅读:
    网络集群
    数组集合删除算法
    数组集合添加算法
    网络编程的认识
    NFC and Contactless Technologies
    斐波那契数列-有一对兔子
    Android历史版本
    最大公约数及最小公倍数是个什么东西
    要知其然还要知其所以然printChar
    Android项目Library导入的问题整理
  • 原文地址:https://www.cnblogs.com/huntfor/p/3855727.html
Copyright © 2020-2023  润新知