23. Merge k Sorted Lists 合并K个有序链表

这道题是21题合并2个有序链表的升级版本,看了许多解题思路:

    A:直接暴力解锁,全部放进一个堆,然后依次吐出来;

    B:利用21题的算法,循环一次做两两合并,这样就得到结果;但是时间复杂度有点差;

    C:利用归并排序思想,进行分治;其实就是利用递归,牺牲空间,提升时间效率;

存在的问题是:看过了许多解答后发现,大家基于的给定数据类型是 List<ListNode>/ArrayList<ListNode>,然后,现在系统更新了,给的数据类型是 ListNode[] lists,所以,我现在重新设计的这个题目绝对大家赏心悦目!

我先贴一个我在讨论当中搜到的原始程序:

 public ListNode mergeKLists(ListNode[] lists) {
    if (lists == null || lists.length== 0)
        return null;
    if(lists.length==1){
        return lists[0];
    }
     return mergeKLists(lists,0,lists.length-1);
 }
 public ListNode mergeKLists(ListNode[] lists, int lo, int hi) {
          int m=lo+(hi-lo)/2;
          ListNode left=null;
            if(m<=lo){
              left=lists[m];
            }else{
              left=mergeKLists(lists,lo,m);      
            }
          ListNode right=null;
          if(m+1>=hi){
              right=lists[hi];
          }else{
            right=mergeKLists(lists,m+1,hi);    
          }
         return  merge2List(left,right);
}

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

        }else{
            cur.next=list2;
            list2=list2.next;
        }
        cur=cur.next;
    }
    return dummy.next;
}

很聪明,利用桥接,将问题套到了归并排序或者说是二分法的经典套路上面来。我当时想了很久这该怎么办。当然,时间换来的记忆还是值得的。希望这个方法,在未来的开发当中能排上用处。

另外,我对他的分治进行了优化。因为,考虑到除法取整问题后,我发现不论是“奇数个数数组还是偶数个数数组”分治的归宿,或者说底层就2种情况:(A,A)(A,A+1)两种情况,其他情况都可以分治到这两种情况上面来。所以针对这两种情况单独设计返回相当合适!

public class Solution {
    public ListNode merge2Lists(ListNode l1, ListNode l2){
        ListNode head = new ListNode(-1);
        ListNode index = head;
        while(l1 != null && l2 != null){
            if(l1.val < l2.val)
            {
                index.next = l1;
                l1 = l1.next;
                index = index.next;
            }
            else{
                index.next = l2;
                l2 = l2.next;
                index = index.next;
            }
        }
        if (l1 != null)
          index.next = l1;
        else
          index.next = l2;
        return head.next;
    }
    public ListNode mergeKLists(ListNode[] lists, int lo, int hi){
        if (lo == hi) return lists[lo];
        int mid = lo + (hi - lo)/2;
        if (hi == lo + 1)
           {
               return merge2Lists(lists[lo],lists[hi]);
           }
        ListNode left = mergeKLists(lists, lo, mid);
        ListNode right = mergeKLists(lists, mid+1, hi);
        return merge2Lists(left,right);
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0) return null;
        if (lists.length == 1) return lists[0];
        return mergeKLists(lists, 0, lists.length-1);
    }
}

 

转载于:https://www.cnblogs.com/ProWhalen/p/5380695.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值