Leetcode第23题思悟——合并K个排序链表(merge-k-sorted-lists)
知识点预告
- 分治思想
题目要求
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的思路
这道题是第21题——合并两个有序链表的扩展版;
我的思路是每次从K个链表的头结点中选出最小的那个节点,然后将其移出;不断扩展,直到所有节点都被移出;
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null||lists.length==0){
return null;
}
ListNode head=new ListNode(-1);
ListNode tail=head;
List<ListNode> pointers=new ArrayList<>();
ListNode currentNode;
for(int i=0;i< lists.length;i++){
currentNode=lists[i];
if(currentNode!=null){
pointers.add(lists[i]);
}
}
int restNum=pointers.size();
int minValue;
int maxIndex=-1;
while(restNum>0){
minValue=Integer.MAX_VALUE;
for(int i=0;i<restNum;i++){
currentNode=pointers.get(i);
if(currentNode.val<minValue){
maxIndex=i;
minValue=currentNode.val;
}
}
tail.next=pointers.get(maxIndex);
tail=tail.next;
if(tail.next==null) {//是该链条的最后一个结点
restNum--;
pointers.remove(maxIndex);
}else{
pointers.set(maxIndex,tail.next);
}
}
return head.next;
}
优秀解法
//解法A
public ListNode mergeKLists(ListNode[] lists){
if(lists.length == 0)
return null;
if(lists.length == 1)
return lists[0];
if(lists.length == 2){
return mergeTwoLists(lists[0],lists[1]);
}
int mid = lists.length/2;
ListNode[] l1 = new ListNode[mid];
for(int i = 0; i < mid; i++){
l1[i] = lists[i];
}
ListNode[] l2 = new ListNode[lists.length-mid];
for(int i = mid,j=0; i < lists.length; i++,j++){
l2[j] = lists[i];
}
return mergeTwoLists(mergeKLists(l1),mergeKLists(l2));
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
ListNode head = null;
if (l1.val <= l2.val){
head = l1;
head.next = mergeTwoLists(l1.next, l2);
} else {
head = l2;
head.next = mergeTwoLists(l1, l2.next);
}
return head;
}
差异分析
我的解法基于以下认识:
- K个链表是有序的;
- 从K个链表中选出最小的节点,加入合并后的大链表里,以此扩展大链表;
- K个链表的头结点中最小的节点就是K个链表里最小的节点,也就是将被添加到大链表里的节点;
于是问题转化为在K个节点中寻找最小的节点;
优秀解法基于以下认识:
- 合并两个有序链表是简单的;
- 合并K个有序链表可以通过分治的思想,逐渐缩小K,直到K=1,或者0;
我的解法专注于一题,优秀解法所体现的分治思想,可以解决一类题;