方法1:优先队列
利用java自带的优先队列,通过自定义Comparator实现最小堆,然后将ListNode数组中各个链表的头结点放入优先队列中。优先队列的首个元素即为返回结果的头结点。
然后对队列进行遍历,每取出一个节点后,判断其是否指向下一个节点,若是,则将其下一节点添加入队列,直到整个优先队列为空。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length==0){
return null;
}
ListNode dummyHead = new ListNode(-1);
ListNode curr = dummyHead;
Queue<ListNode> q = new PriorityQueue<>(new Comparator<ListNode>(){
@Override
public int compare(ListNode node1, ListNode node2){
return node1.val - node2.val;
}
});
//将全部头结点放入优先队列
for(ListNode node : lists){
//头结点可能为null
if(node == null)continue;
q.offer(node);
}
while(!q.isEmpty()){
ListNode next = q.poll();
curr.next = next;
curr = curr.next;
if(next.next != null){
q.offer(next.next);
}
}
return dummyHead.next;
}
}
方法2:分治法
对k个链表进行合并,可以视为对2个链表进行合并,一共进行k-1次合并操作。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null;
return merge(lists, 0, lists.length - 1);
}
private ListNode merge(ListNode[] lists, int left, int right) {
if (left == right) return lists[left];
int mid = left + (right - left) / 2;
ListNode l1 = merge(lists, left, mid);
ListNode l2 = merge(lists, mid + 1, right);
return mergeTwoLists(l1, l2);
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}