给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [
1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:输入:lists = [] 输出:[] 示例 3:
输入:lists = [[]] 输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-104 <= lists[i][j] <= 104
lists[i] 按 升序 排列
lists[i].length 的总和不超过 104
(简单暴力)两两合并
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0){
return null;
}
for(int i = 1;i < lists.length;i++){
lists[0] = sort(lists[0],lists[i]);
}
return lists[0];
}
i.非递归合并(链表无头指针)
public ListNode sort(ListNode list1,ListNode list2){
ListNode q;
if(list1!=null && list2!=null){
if(list1.val <= list2.val){
q = list1;
list1 = list1.next;
}else{
q = list2;
list2 = list2.next;
}
}else if(list1==null && list2==null){
return null;
}else{
return list1!=null?list1:list2;
}
ListNode h = q;
while(list1!=null && list2!=null){
if(list1.val <= list2.val){
q.next = list1;
list1 = list1.next;
}else{
q.next = list2;
list2 = list2.next;
}
q = q.next;
}
if(list1 != null){
q.next = list1;
}else{
q.next = list2;
}
return h;
}
i.非递归合并(链表有头指针)
(看的大佬的思路之后发现可以使用头指针,然后改了一下上面的代码,果然好看多了QAQ
public ListNode sort(ListNode list1,ListNode list2){
ListNode q = new ListNode();
ListNode h = q;
while(list1!=null && list2!=null){
if(list1.val <= list2.val){
q.next = list1;
list1 = list1.next;
}else{
q.next = list2;
list2 = list2.next;
}
q = q.next;
}
if(list1 != null){
q.next = list1;
}else{
q.next = list2;
}
return h.next;
}
iii.递归合并
(代码确实简洁,但是运行时间长了一倍还多
public ListNode sort(ListNode p1,ListNode p2){
if(p1==null){
return p2;
}
if(p2==null){
return p1;
}
if(p1.val<=p2.val){
p1.next = sort(p1.next,p2);
return p1;
}else{
p2.next = sort(p1,p2.next);
return p2;
}
}
K 指针:K 个指针分别指向 K 条链表
(这是大佬的代码
一开始自己想到的循环条件太差于是便舍弃了这一种方法……来借鉴一下大佬的算法orz
public ListNode mergeKLists(ListNode[] lists) {
int k = lists.length;
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead;
while (true) {
ListNode minNode = null;
int minPointer = -1;
for (int i = 0; i < k; i++) {
if (lists[i] == null) {
continue;
}
if (minNode == null || lists[i].val < minNode.val) {
minNode = lists[i];
minPointer = i;
}
}
if (minPointer == -1) {
break;
}
tail.next = minNode;
tail = tail.next;
lists[minPointer] = lists[minPointer].next;
}
return dummyHead.next;
}
优先队列
(也是看的大佬的解题思路
学了优先队列之后都没有用过……
确实比上面几种方法快太多太多
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null || lists.length == 0){
return null;
}
PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
if(o1.val < o2.val){
return -1;
}else if(o1.val == o2.val){
return 0;
}else{
return 1;
}
}
});
ListNode h = new ListNode();
ListNode p = h;
for(ListNode list : lists){
if(list != null){
queue.add(list);
}
}
while(!queue.isEmpty()){
p.next = queue.poll();
p = p.next;
if(p.next!=null){
queue.add(p.next);
}
}
return h.next;
}