html制作手机网站/长沙官网优化公司
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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
- -10^4 <= lists[i][j] <= 10^4
- lists[i] 按 升序 排列
- lists[i].length 的总和不超过 10^4
解题思路
1.新链表的下一个节点一定是k个链表头中的最小节点
2.考虑选择使用最小堆
解题步骤
1.构建一个最小堆,并依次把链表头插入堆中
2.弹出堆顶接到输出链表,并将堆顶所在链表的新链表头插入堆中
3.等堆元素全部弹出后,合并工作就完成了
时空分析
时间复杂度:O(nlogk)
空间复杂度:O(k)
代码
/*** Definition for singly-linked list.* function ListNode(val, next) {* this.val = (val===undefined ? 0 : val)* this.next = (next===undefined ? null : next)* }*/
class MinHeap {constructor() {this.heap = [];}// 交换节点位置swap(i1, i2) {[this.heap[i1], this.heap[i2]] = [this.heap[i2], this.heap[i1]];}// 获得父节点getParentIndex(i) {return (i - 1) >> 1;}// 获得左节点getleftIndex(i) {return 2 * i + 1;}// 获得右节点getrightIndex(i) {return 2 * i + 2;}// 上移shiftUp(index) {if (index === 0) return;const parentIndex = this.getParentIndex(index);if (this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val) {this.swap(parentIndex, index);this.shiftUp(parentIndex);}}// 下移shiftDown(index) {const leftIndex = this.getleftIndex(index);const rightIndex = this.getrightIndex(index);if (this.heap[leftIndex] && this.heap[leftIndex].val < this.heap[index].val) {this.swap(leftIndex, index);this.shiftDown(leftIndex);}if (this.heap[rightIndex] && this.heap[rightIndex].val < this.heap[index].val) {this.swap(rightIndex, index);this.shiftDown(rightIndex);}}// 插入insert(value) {this.heap.push(value);this.shiftUp(this.heap.length - 1);}// 删除堆顶pop() {if(this.size() === 1) return this.heap.shift()const top = this.heap[0]// pop()方法删除数组最后一个元素并返回,赋值给堆顶this.heap[0] = this.heap.pop();// 对堆顶重新排序this.shiftDown(0);return top}// 获取堆顶peek() {return this.heap[0];}// 获取堆的大小size() {return this.heap.length;}
}
/*** @param {ListNode[]} lists* @return {ListNode}*/
var mergeKLists = function(lists) {const res = new ListNode(0)let p = resconst h = new MinHeap()// 插入k个升序链表的头部节点lists.forEach(l => {if(l) h.insert(l)})// 不断的地比较最小堆中k个节点的大小while(h.size()) {const n = h.pop()p.next = np = p.nextif(n.next) h.insert(n.next)}return res.next
};