NC51:合并k个已排序的链表
合并k个已排序的链表
http://www.nowcoder.com/questionTerminal/65cfde9e5b9b4cf2b6bafa5f3ef33fa6
解法1:优先级队列
优先级队列:小根堆
PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>(){
public int compare(Integer a,Integer b){
return a.compareTo(b);
}
});
// PriorityQueue<Integer> queue = new PriorityQueue();最小k个数:大根堆
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(k,new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o2.compareTo(o1);
}
});
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(k,(a,b)->b.compareTo(a)); 代码:
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Comparator;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode mergeKLists(ArrayList<ListNode> lists) {
if(lists == null || lists.size() < 0){
return null;
}
PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>(){
public int compare(Integer a,Integer b){
return a.compareTo(b);
}
});
// PriorityQueue<Integer> queue = new PriorityQueue();
for(ListNode node : lists){
while(node != null){
queue.add(node.val);
node = node.next;
}
}
ListNode res = new ListNode(0);
ListNode tmp= res;
while(!queue.isEmpty()){
ListNode temp = new ListNode(queue.poll());
tmp.next = temp;
tmp = tmp.next;
}
return res.next;
}
}解法2:递归
如果表1当前值小于表2当前值,表1当前值成为新链表的表头,否则返回表2的当前值作为新链表的表头。 比较当前链表的值,较小的取其子链表继续递归。
当有一个链表取到子链表为空时,说明已经比较完成,可以直接返回非空的链表,返回值赋给了l1.next或者l2.next,但无论如何,最终还是沿着递归链不断返回,最终返回的是新有序链表的表头。
public ListNode mergeKLists(ArrayList<ListNode> lists) {
ListNode result=null;
for(ListNode list : lists){
result=MergeList(result,list);
}
return result;
}
public ListNode MergeList(ListNode list1,ListNode list2){
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
ListNode newHead=null;
if(list1.val>list2.val){
newHead=list2;
list2.next=MergeList(list1,list2.next);
}
else{
newHead=list1;
list1.next=MergeList(list1.next,list2);
}
return newHead;
}解法3:递归+归并排序的思路
public ListNode mergeKLists(ArrayList<ListNode> lists) {
if(lists == null || lists.length == 0){
return null;
}
return mergeList(lists, 0, lists.length - 1);
}
public ListNode mergeList(ListNode[] lists, int left, int right){
if(left >= right)
return lists[left];
int mid = left + (right - left) / 2;
ListNode l1 = mergeList(lists, left, mid);
ListNode l2 = mergeList(lists, mid + 1, right);
return merge(l1, l2);
}
public ListNode merge(ListNode l1, ListNode l2){
if(l1 == null) return l2;
if(l2 == null) return l1;
ListNode ans = new ListNode(0);
ListNode p = ans;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
p.next = l1;
l1 = l1.next;
}
else{
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
p.next = l1 == null? l2 : l1;
return ans.next;
}解法4:循环遍历
思路: 已经解决了两个排序链表的问题,则k个链表的排序也进行依次遍历即可解决;
因为两个链表合并的时间复杂度是O(n),空间复杂度是O(1);
k个链表是外加一次循环,所以时间复杂度为O(n*m)
(n为lists数组的长度,m为数组中链表的长度),空间复杂度为O(1)
public ListNode mergeKLists(ArrayList<ListNode> lists) {
ListNode result=null;
for(ListNode list : lists){
result=MergeList(result,list);
}
return result;
}
public ListNode MergeList(ListNode l1,ListNode l2){
ListNode tmp = new ListNode(-1);
ListNode cur = tmp;
while(l1 != null && l2 != null) {
if(l1.val < l2.val) {
cur.next = l1;
l1 = l1.next;
}
else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
if(l1 == null) cur.next = l2;
// l1遍历为空 那么l2还有节点呢,所以指向l2的节点。
if(l2 == null) cur.next = l1;
// l2遍历为空 那么l1还有节点呢,所以指向l1的节点。
return tmp.next;
}名企高频面试算法题解 文章被收录于专栏
牛客题霸 - 程序员面试高频题 - 题解

