[LeetCode] Merge K Sorted Linked Lists

本文提供三种解决LeetCode合并K个排序链表问题的方法:暴力破解、使用小顶堆及分而治之策略。通过对比不同算法的时间与空间复杂度,帮助读者理解每种方法的特点。

题目链接: https://oj.leetcode.com/problems/merge-k-sorted-lists/

 

问题:

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

 

解题思路:

方法一:暴力破解

思路:

将列表一个一个地合并(例如:lists = [l1, l2, l3, l4],首先合并l1和l2,然后将合并后的结果与l3合并,…)

复杂度分析:

时间:

假设有k个列表,每个列表的长度为n,需要k-1次合并操作,第1次操作将2个长度为n的列表合并,最多需要n+n次比较,第二次操作将一个长度为2n和一个长度为n的列表合并,最多需要2n+n次比较,后一次合并需要的最多比较次数比前一次合并多n,所以总的比较次数为 2n + 3n +4n + … + kn = n(k(k+1)/2 - 1) = O(nk^2)

 

方法二:运用小顶堆

思路:

小顶堆的大小为k

1)首先用每个列表的最小元素初始化堆;

2)从堆中返回最小元素之后将它所在的列表中下一个元素插入堆中;

3)重复2)中操作,直到所有列表为空

复杂度分析:

时间:

总共有nk个元素,将每个元素插入堆的操作时间复杂度为O(logk)。

所以,总时间复杂度为O(nklogk)

空间:

额外分配的堆空间为O(k)

 1     private static final Comparator<ListNode> listComparator = new Comparator<ListNode>(){
 2         @Override
 3         public int compare(ListNode x, ListNode y) {
 4             return x.val - y.val;
 5         }
 6     };
 7     
 8     public ListNode mergeKLists(ListNode[] lists) {
 9         if(lists.length == 0){
10             return null;
11         }
12         Queue<ListNode> queue = new PriorityQueue<>(lists.length, listComparator);
13         
14         for(ListNode node: lists){
15             if(node != null){
16                 queue.add(node);
17             }
18         }
19         
20         ListNode dummyHead = new ListNode(0);
21         ListNode p = dummyHead;
22         while (!queue.isEmpty()){
23             ListNode node = queue.poll();
24             p.next = node;
25             p = p.next;
26             if(node.next != null){
27                 queue.add(node.next);
28             }
29         }
30         return dummyHead.next;      
31     }  

 

方法三:分而治之

思路:

采用两两合并的方法

列表数目变化为:k -> k/2 -> k/4 -> … -> 2 -> 1

同时,列表长度变化为: n -> 2n -> 4n -> … -> n * 2^logk 

复杂度分析:

时间:

k * n + (k / 2) *2n + … +  n * 2^logk  * 1

= nk + nk + …+ nk

= nklogk

总时间复杂度为O(nklogk)

空间:

O(1)

 1         public ListNode mergeKLists(ListNode[] lists) {
 2         if(lists.length == 0){
 3             return null;
 4         }
 5         int end = lists.length - 1;
 6         while(end > 0){
 7             int begin = 0;
 8             while(begin < end){
 9                 lists[begin] = merge2Lists(lists[begin], lists[end]);
10                 begin++;
11                 end--;
12             }
13         }
14         return lists[0];
15     }
16     
17     private ListNode merge2Lists(ListNode l1, ListNode l2){
18         ListNode dummyHead = new ListNode(0);
19         ListNode p = dummyHead;
20         while(l1 != null && l2 != null){
21             if(l1.val < l2.val){
22                 p.next = l1;
23                 l1 = l1.next;
24             }else{
25                 p.next = l2;
26                 l2 = l2.next;
27             }
28             p = p.next;
29         }
30         if(l1 != null){
31             p.next = l1;
32         }
33         if(l2 != null){
34             p.next = l2;
35         }
36         return dummyHead.next;
37     }
38     

 

 

转载于:https://www.cnblogs.com/momo-fun/p/5788359.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值