題目描述:
合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。
示例:
輸入:
[
1->4->5,
1->3->4,
2->6
]
輸出: 1->1->2->3->4->4->5->6
思路:
1.遍歷一遍所有鏈表(O(N)),將所有元素加入到列表中,對列表排序(O(NlogN)),然後添加到一個新的鏈表(空間複雜度 O(N))返回
public static ListNode mergeKLists(ListNode[] lists) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < lists.length; i++) {
ListNode node = lists[i]; // 得到每一個鏈表的頭節點
while (node != null) {
list.add(node.val);
node = node.next;
}
}
Collections.sort(list);
ListNode root = new ListNode(-1);
ListNode copy = root;
for (Integer val : list) {
copy.next = new ListNode(val);
copy = copy.next;
}
return root.next;
}
2.利用優先隊列,也就是小頂堆,然後每次彈出最小的,重建鏈表
/**
* 時間複雜度: O(Nlogk) ,其中k 是鏈表的數目
* 空間複雜度:
* O(n) 創造一個新的鏈表需要 O(n)
* @param lists
* @return
*/
public static ListNode mergeKLists2(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
ListNode head = new ListNode(0);
//優先隊列--->也就是小頂堆
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for (ListNode node : lists) {
while (node != null) {
pq.add(node.val);
node = node.next;
}
}
ListNode curr = head;
while (!pq.isEmpty()) { //每次彈出來最小的
curr.next = new ListNode(pq.poll());
curr = curr.next;
}
return head.next;
}