Merge k Sorted Lists-LeetCode

    xiaoxiao2021-03-25  59

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

    题目描述:归并排序k个有序单链表。(感觉LeetCode说到排序默认即是自然会顺序,数字递增,字母按顺序)

    题目思路:

    【超时思路】先说一个由二路归并得来的思维简单、看似取巧实则复杂度奇高的方法:直接k路归并。

    1.内循环: 在lists指向的k个链表元素之间选出一个最小的lists[i],链接到最终要输出的链表上去,再将lists[i]指向最小元素的下一个节点。

    2.外循环:

    循环上述过程直到lists都为空。

    复杂度分析:假设有n个长度都为m的有序链表在归并,那么总的比较次数是多少呢?取出一个元素要比较n次,那么总共要经历O(n*n*m)次比较才可以完全归并。这复杂度交LeetCode上,妥妥的超时了。

    超时代码:

    class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public class Solution { /** 思路简单,但是最坏复杂度很高的算法。比如n个单链表都只有一个元素,用该方法归并却需要n*n次大小比较,复杂度太高了 * @param lists * @return */ public ListNode mergeKLists(ListNode[] lists) { ListNode result=new ListNode(0),p=result; int k=0,min=0; while(true){ min=Integer.MAX_VALUE; k=-1; for(int i=0;i<lists.length;i++){ //每次都从lists[]所指向的头里挑出来一个最小的,加入有序单链表 if(lists[i]!=null && min>=lists[i].val){ //记录最小值和index位置 min=lists[i].val; k=i; } } if(k==-1){ //若在本轮查找中,没有进入比较环节,则所有链表都到头了,退出循环返回 p.next=null; break; }else{ p=p.next=lists[k]; lists[k]=lists[k].next; } } return result.next; } }

    【AC思路】AC代码的思路本质也是建立在二路归并排序上的,即将lists的链表两两两路归并,最后得到最后的一路链表输出即可。粗略的看,整体复杂度最大不超过O(n2logn)。

    import java.lang.Math; class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public class Solution { public ListNode mergeKLists(ListNode[] lists) { if(lists.length>0){ //如果lists中的元素数在1一下,就不用归并了,直接输出就好 int Niterator=(int)Math.ceil(Math.log(lists.length)/Math.log(2)); //在lists中使用二路归并,要归并多少层(8进4视为一层,4进2视为一层),做法就是log2(lists.length)再向上取整就行了 for(int i=1;i<=Niterator;i++){ int interval=(int)Math.pow(2, i); //对于不同的归并层,计算每个归并组的间隔,最底层2,上一层4,再上一层8,就这么来 for(int j=0;j+interval/2<lists.length;j+=interval){ lists[j]=mergeTwoLists(lists[j],lists[j+interval/2]); //在每一组内做二路归并,把结果给到这组的首个位置上保存,j+interval/2这个值的由来大家画个满二叉树体会一下就好了 } } return lists[0]; }else return null; } public ListNode mergeTwoLists(ListNode l1, ListNode l2) { //二路归并,O(N)复杂度,太简单啦 ListNode result=new ListNode(0),p=result,p1=l1,p2=l2; while(p1!=null&&p2!=null){ if(p1.val<p2.val){ p=p.next=p1; p1=p1.next; }else{ p=p.next=p2; p2=p2.next; } } p.next=(p1==null?p2:p1); //一个链表先耗尽,就把另一个接到已有序的链表末位 return result.next; } }

    public class Main{ public static void main(String[] args){ /*Scanner in=new Scanner(System.in); String target=in.nextLine();*/ ListNode[] lists=new ListNode[0]; for(int j=0;j<lists.length;j++){ lists[j]=new ListNode(1); ListNode temp=lists[j]; for(int i=2;i<=6;i++){ temp.next=new ListNode(i); temp=temp.next; } temp.next=null; } long startTime=System.currentTimeMillis(); Solution find=new Solution(); ListNode temp=find.mergeKLists(lists); long endTime=System.currentTimeMillis(); long excTime=(long)(endTime-startTime); System.out.println("执行时间:"+excTime+"ms"); for(int i=0;temp!=null;i++){ System.out.println(temp.val); temp=temp.next; } } }

    转载请注明原文地址: https://ju.6miu.com/read-39336.html

    最新回复(0)