三种解法
- 分治
- 顺序合并
- 优先队列
首先做这道题,得先会一道基础的题目,没做过的可以先去做
合并两个已排序的链表
分治(归并)
先分而治之,分到不能再分则合并(归并)
图解:
import java.util.*; public class Solution { public ListNode mergeKLists(ArrayList<ListNode> lists) { return merge(lists,0,lists.size()-1); } public ListNode merge(ArrayList<ListNode> lists, int l, int r){ // 左右相等说明不能再分 if(l == r) return lists.get(l); if(l > r){ return null; } int mid = l + (r-l)/2; return mergeTwoList(merge(lists,l,mid),merge(lists,mid+1,r)); } //合并两个有序链表 public ListNode mergeTwoList(ListNode node1, ListNode node2){ ListNode node = new ListNode(-1); ListNode tmp = node; while(node1!=null && node2!=null){ if(node1.val <= node2.val){ tmp.next = node1; node1 = node1.next; }else{ tmp.next = node2; node2 = node2.next; } tmp = tmp.next; } tmp.next = node1!=null?node1:node2; return node.next; } }
遍历合并
图解:
import java.util.*; public class Solution { public ListNode mergeKLists(ArrayList<ListNode> lists) { int n = lists.size(); if(n == 0) return null; if(n == 1) return lists.get(0); ListNode node = lists.get(0); for(int i = 1; i < n; i++){ node = margeTwoList(lists.get(i),node); } return node; } public ListNode margeTwoList(ListNode node1, ListNode node2){ ListNode node = new ListNode(-1); ListNode tmp = node; while(node1!=null && node2!=null){ if(node1.val <= node2.val){ tmp.next = node1; node1 = node1.next; }else{ tmp.next = node2; node2 = node2.next; } tmp = tmp.next; } tmp.next = node1!=null?node1:node2; return node.next; } }
使用优先队列
用优先队列建一个小顶堆,每次堆顶为值最小的节点,依次取出,然后再将它的下一个节点放回去。
再重复过程~
public class Solution { public ListNode mergeKLists(ArrayList<ListNode> lists) { //小根堆 Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val); //将全部的节点放进去 for (ListNode node: lists) { if (node != null) { pq.offer(node); } } ListNode dummyHead = new ListNode(0); ListNode tail = dummyHead; while (!pq.isEmpty()) { //队首为值最小的节点 ListNode minNode = pq.poll(); tail.next = minNode; tail = minNode; //若拿出来的节点的下一个节点不为null,则再将其放回去 if (minNode.next != null) { pq.offer(minNode.next); } } return dummyHead.next; } }