zoukankan      html  css  js  c++  java
  • Merge k Sorted Lists, k路归并

    import java.util.Arrays;
    import java.util.List;
    import java.util.PriorityQueue;
    /*
    class ListNode
    {
        ListNode next;
        int val;
        ListNode(int x)
        {
            val = x;
        }
    }
    */
    //k路归并问题
    public class MergKSortedLists {
    
    
        //二路归并,这个算法时间复杂度o(2n)
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            ListNode dumy = new ListNode(0);
            ListNode head = dumy;
            while (l1 != null && l2 != null) {
                if (l1.val < l2.val) {
                    dumy.next = l1;
                    l1 = l1.next;
                } else {
                    dumy.next = l2;
                    l2 = l2.next;
                }
                dumy = dumy.next;
            }
            if (l1 == null) {
                dumy.next = l2;
            }
            if (l2 == null) {
                dumy.next = l1;
            }
            return head.next;
        }
        //利用二路归并进行k路归并,时间复杂度o(2kn),leetcode显示time limits exceeds
        public ListNode mergeKLists1(ListNode[] lists)
        {
            if(lists.length == 0)
            {
                return null;
            }
            ListNode head = lists[0];
            for(int i = 1; i < lists.length; i ++)
            {
                head = mergeTwoLists(head, lists[i]);
            }
            return head;
        }
        
        //网上看到的很有意思的想法。就把ListNode当做一个整数,这道题,正好看做数组的二路归并排序,不过数组里面的元素是节点
        //这种方法显然也是超时的,这种思想,看似是二路归并,其实并不是,粒度不一样。这个算法的时间复杂度也并不是O(nlgn)
        public ListNode mergerKlists2(ListNode[] lists)
        {
            //自顶向下的二路归并,递归
            if(lists.length == 0)
            {
                return null;
            }
            List<ListNode> a = Arrays.asList(lists);
            return helper(a);
        }
        public ListNode helper(List<ListNode> lists)
        {
            if(lists.size() == 1)
            {
                return lists.get(0);
            }
            int len = lists.size();
            int mid = len/2;
            ListNode l1 = helper(lists.subList(0, mid));
            ListNode l2 = helper(lists.subList(mid, len));
            return mergeTwoLists(l1, l2);
        }
            
    
        //利用PriorityQueue的特性,也很巧妙,并且AC
        //算法思想是:比较所有k个数组的头一个元素,找到最小的那一个,然后取出来。
        //我们在该最小元素所在的数组取下一个元素,然后重复前面的过程去找最小的那个。这样依次循环直到找到所有的元素。
        public ListNode mergeKLists3(ListNode[] lists)
        {
            if(lists.length == 0)
                return null;
            //由于ListNode并没有实现comparable接口,我们必须自定义排序规则,可实现comparator接口,comparator是函数式接口
            //comparable接口是在方法内的,而comparator接口是在方法外的注意区别两者
            PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2)->
            {
                ListNode l1 = (ListNode)o1;
                ListNode l2 = (ListNode)o2;
                return l1.val > l2.val ? 1 : l1.val < l2.val ? -1 : 0;
            });
            ListNode head = new ListNode(0);
            ListNode p = head;
            for (ListNode list : lists) {
                queue.offer(list);
            }
            while(!queue.isEmpty())
            {
                ListNode n = queue.poll();
                p.next = n;
                p = p.next;
                if(n.next!=null)
                {
                    queue.offer(n.next);
                }
            }
            return head.next;
        }
    }

    堆排序算法后续补充。。。。

  • 相关阅读:
    XCode5中新建工程后强制使用了ARC,如何去掉?
    面向对象程序的设计原则--Head First 设计模式笔记
    ios控件自定义指引
    iOS UITableViewDelegate && UITableViewDataSource 执行顺序
    awakeFromNib方法和viewDidLoad方法区别
    ios 视图的旋转及应用
    线段树模板 (刘汝佳)
    poj 3468
    hdu 2829(四边形优化 && 枚举最后一个放炸弹的地方)
    poj 3517(约瑟夫环问题)
  • 原文地址:https://www.cnblogs.com/masterlibin/p/5557297.html
Copyright © 2011-2022 走看看