zoukankan      html  css  js  c++  java
  • 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.

    思路:

      归并排序(二分问题)

    我的代码:

    public class Solution {
        public ListNode mergeKLists(List<ListNode> lists) {
            if(lists == null || lists.size() == 0) return null;
            if(lists.size() == 1) return lists.get(0);
            int n = lists.size();
            int i = 0;
            List<ListNode> left = new ArrayList<ListNode>();
            List<ListNode> right = new ArrayList<ListNode>();
            while(i < n/2)
            {
                left.add(lists.get(i));
                i++;
            }
            while(i < n)
            {
                right.add(lists.get(i));
                i++;
            }
            ListNode leftNode = mergeKLists(left);
            ListNode rightNode = mergeKLists(right);
            return mergeTwoLists(leftNode, rightNode);
        }
          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            ListNode dummy = new ListNode(-1);
            ListNode rst = dummy;
            rst.next = null;
            while(l1 != null && l2 != null)
            {
                int val1 = l1.val;
                int val2 = l2.val;
                if(val1 < val2)
                {
                    dummy.next = l1;
                    l1 = l1.next;
                }
                else
                {
                    dummy.next = l2;
                    l2 = l2.next;
                }
                dummy = dummy.next;
            }
            if(l1 != null)
            {
                dummy.next = l1;
            }
            if(l2 != null)
            {
                dummy.next = l2;
            }
            return rst.next;
        }
    }
    View Code

    他人代码1:

    /*
            SOL 1:
              使用merge sort和分治法完成
        */
        public ListNode mergeKLists1(List<ListNode> lists) {
            // 记得加上这个合法性判断。
            if (lists == null || lists.size() == 0) {
                return null;
            }
            
            return helper(lists, 0, lists.size() - 1);
        }
        
        /*
        l, r表示list的左右边界
        */
        public ListNode helper(List<ListNode> lists, int l, int r) {
            if (l < r) {
                int mid = l + (r - l) / 2;
                
                /*
                   分治法。把问题分为2个更小的子问题:左边list的merge,和右边list的merge.
                   再把2个生成的解合并在一起。
                */
                return merge(helper(lists, l, mid), helper(lists, mid + 1, r));
            }
            
            return lists.get(l);
        }
        
        public ListNode merge(ListNode n1, ListNode n2) {
            ListNode dummy = new ListNode(0);
            ListNode cur = dummy;
            
            while (n1 != null && n2 != null) {
                if (n1.val < n2.val) {
                    cur.next = n1;
                    n1 = n1.next;
                } else {
                    cur.next = n2;
                    n2 = n2.next;
                }
                
                cur = cur.next;
            }
            
            if (n1 != null) {
                cur.next = n1;
            } else {
                cur.next = n2;
            }
            
            return dummy.next;
        }
    View Code

    他人代码2:

    /*
            SOL 2:
              使用 priority Queue.
        */
        public ListNode mergeKLists(List<ListNode> lists) {
            // 记得加上这个合法性判断。
            if (lists == null || lists.size() == 0) {
                return null;
            }
            
            int size = lists.size();
            
            PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(size, 
                new Comparator<ListNode>() {
                    // 注意,此处参数用ListNode
                    public int compare(ListNode o1, ListNode o2) {
                        return o1.val - o2.val;
                    }
                }
            );
            
            // Add all the head node to the priority queue.
            for (ListNode node: lists) {
                if (node != null) {
                    // Should skip the null node.s
                    q.offer(node);    
                }
            }
            
            ListNode dummy = new ListNode(0);
            ListNode tail = dummy;
            
            while (!q.isEmpty()) {
                // get the smallest node from the queue.
                ListNode cur = q.poll();
                
                tail.next = cur;
                tail = tail.next;
                
                // 将下一个节点补充进来。
                if (cur.next != null) {
                    q.offer(cur.next);
                }
            }
            
            return dummy.next;
        }
    View Code

    学习之处:

    • 此问题亦是二分查找的变形,我的方法是通过个数进行划分。
    • 而他人的代码通过left和right就比较成功了,对于递归中,left == right的情况也catch到了 left<right的地方也catch到了,十分完美的算法
    • 通过最小堆的方式亦可以解决这个问题,最小堆这个数据结果需要学习一下,建立堆的时间复杂度为O(nlgn),以当所有链表都读完时结束,这个时候所有元 素按从小到大放在结果链表中。这个算法每个元素要读取一次,即是k*n次,然后每次读取元素要把新元素插入堆中要logk的复杂度,所以总时间复杂度是 O(nklogk)。空间复杂度是堆的大小,即为O(k)
  • 相关阅读:
    Eclipse 导入外部项目无法识别为web项目并且无法在部署到tomcat下
    Android开发-API指南-<activity-alias>[原创译文]
    深入WeakHashMap
    寻找第K大数的方法总结
    overridePendingTransition的简介
    Oracle执行CreateTableAs报ORA-600错误
    HahaMil数据库(数据库操作组件)
    List(支持按笔画排序的List类)
    关于我的网站(八零家园三周年)
    走出象牙塔之Final(2014.07.07)
  • 原文地址:https://www.cnblogs.com/sunshisonghit/p/4334361.html
Copyright © 2011-2022 走看看