Topic describes
You are given an array of linked lists, each of which has been sorted in ascending order.
Please merge all lists into one ascending list and return the merged list.
Their thinking
algorithm
Multiple merge, small top heap
Train of thought
We use the small top heap to maintain the list head node that stores the minimum value
Insert all the list head nodes into the heap first
One thing to note here is that we’re maintaining the small top heap, filling in the list nodes, and the comparison function is comparing the values of the nodes
Then constantly extract the head node to merge it into the new linked list (RET)
After the merge, we need to see if the popup header, cur, exists in cur.next, and if there are any subsequent elements, we need to insert them into the heap, and continue as long as there are elements in the heap
Finally, ret.next, the head node of the new list, is returned
code
/** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */
/ * * *@param {ListNode[]} lists
* @return {ListNode}* /
// list, heap, merge sort
function ListNode(val, next) {
this.val = val === undefined ? 0 : val
this.next = next === undefined ? null : next
}
const l1 = new ListNode(1.new ListNode(4.new ListNode(5)))
const l2 = new ListNode(1.new ListNode(3.new ListNode(4)))
const l3 = new ListNode(2.new ListNode(6))
var mergeKLists = function (lists) {
// The priority queue stores the current positions of all k lists
const h = new Heap((a, b) = > {
if(! b)return false
return a.val > b.val
})
// queue k linked list heads in sequence
for (x of lists) {
if(! x)continue
h.insert(x)
}
// Continuously pop nodes from h and put them at the end of the merged list
let ret = new ListNode(),
p = ret
while(! h.isEmpty()) {const cur = h.extract()
p.next = cur
p = p.next
// If cur.next exists, i.e. the current popup node has a next node, we need to put it into h
if (cur.next) {
h.insert(cur.next)
}
}
return ret.next
}
class Heap {
constructor(compareFn) {
this.compareFn = compareFn
this.heap = []
}
swap(parent, index) {
const arr = this.heap ; [arr[parent], arr[index]] = [arr[index], arr[parent]] }getLeftIndex(index) {
return index * 2 + 1
}
getRightIndex(index) {
return index * 2 + 2
}
getParentIndex(index) {
return Math.floor((index - 1) / 2)}size() {
return this.heap.length
}
isEmpty() {
return this.size() === 0
}
insert(value) {
const index = this.heap.length
this.heap.push(value)
this.siftUp(index)
}
siftUp(index) {
let parent = this.getParentIndex(index)
while (
index > 0 &&
this.compareFn(this.heap[parent], this.heap[index])
) {
this.swap(parent, index)
index = parent
parent = this.getParentIndex(index)
}
}
extract() {
if (this.isEmpty()) return
if (this.size() === 1) return this.heap.pop()
const removedItem = this.heap[0]
this.heap[0] = this.heap.pop()
this.siftDown(0)
return removedItem
}
siftDown(index) {
let element = index
const left = this.getLeftIndex(index)
const right = this.getRightIndex(index)
if (
index < this.size() &&
this.compareFn(this.heap[element], this.heap[left])
) {
element = left
}
if (
index < this.size() &&
this.compareFn(this.heap[element], this.heap[right])
) {
element = right
}
if(element ! == index) {this.swap(element, index)
this.siftDown(element)
}
}
top() {
return this.heap[0]}}Copy the code