LeetCode第23题:合并K个升序链表
这道题由于K是不固定的,Leecode检测题一般又喜欢出几个K值很大的题,所以肯定不能暴力全量循环做。
这里思路一采用小根堆的思想,取出所有链表的头部节点放入小跟堆中,之后从小根堆里取出根节点(当前最小节点),之后将这个根节点的next继续放入小跟读,重复到取完所有节点即可。
/**
* 解法一使用优先级队列
* 小根堆的思想,先取所有链表第一个节点放入小根堆。
* 之后每次从堆顶获取最小元素,再补入放入元素后的下一个节点,循环此过程
*/
public static ListNode mergeKLists2(ListNode[] lists) {
PriorityQueue<ListNode> queue = new PriorityQueue<>(Comparator.comparingInt(x -> x.val));
for (ListNode list : lists) {
if (list != null) {
queue.add(list);
}
}
ListNode ans = new ListNode(0);
ListNode cur = ans;
while (!queue.isEmpty()) {
ListNode listNode = queue.poll();
cur.next = listNode;
cur = cur.next;
if (listNode.next != null) {
queue.add(listNode.next);
}
}
return ans.next;
}
这里额外提供一种思路,归并处理。即将K个链表拆分成两两合并,之后再进行归并,直到最终合并为一个链表即可。
/**
* 解法二思路:归并处理,拆分为N*2个链表,分表合并2个链表,汇总得到结果
*/
public static ListNode mergeKLists(ListNode[] lists) {
if (lists == null) {
return null;
}
return merge(lists, 0, lists.length - 1);
}
public static ListNode merge(ListNode[] nodes, int l, int r) {
if (l == r) {
return nodes[l];
}
if (l > r) {
return null;
}
if (r - l == 1) {
return mergeTwoLists(nodes[l], nodes[r]);
}
int mid = (r + l) / 2;
return mergeTwoLists(merge(nodes, l, mid), merge(nodes, mid + 1, r));
}
/**
* 21题里的合并两个链表,直接拷贝过来的
*/
public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}else if(l2 == null) {
return l1;
}else {
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}else {
l2.next = mergeTwoLists(l2.next, l1);
return l2;
}
}
}