每日一题 -- 堆
1439. 有序矩阵中的第 k 个最小数组和
1439. 有序矩阵中的第 k 个最小数组和
分析
- 数组都是有序的,用 len 个指针指向每一个数组的下标
- 最小堆维护一个最小的总值和它对应的指针数组,每一次出堆的时候,根据它的指针数组,分别对每一个指针向前1位,得到新的指针和数组,再放回堆中
注意
- 由于指针数组的动态变更的,但是[1,0] -> [1,1] 和 [0,1] -> [1,1] 得到的结果是一样的,所以要用 map 保证每次入堆的指针是唯一的
- 由于 map 的 key 不能是数组,所以 map.set 的时候要将数组转成字符串
- 每当出堆的时候的指针数组,需要分别+1,所以需要对数组做一次拷贝
var kthSmallest = function (mat, k) {
const len = mat.length
const arrLen = mat[0].length
let points = new Array(len).fill(0)
const minHeap = new Heap()
minHeap.heappush(points.reduce((pre, val, index) => pre + mat[index][val], 0), points)
const map = new Map()
map.set(arrToString(points),1)
while (--k) {
const [sum, points] = minHeap.heappop()
for (let i = 0; i < len; i++) {
if (points[i] < arrLen-1) {
const temp =[...points]
temp[i] += 1
if(!map.has(arrToString(temp))){
minHeap.heappush(temp.reduce((pre, val, index) => pre + mat[index][val], 0), temp)
map.set(arrToString(temp),1)
}
}
}
}
return minHeap.data[1][0]
};
const arrToString = arr => {
return JSON.stringify(arr)
}
const Heap = function () {
this.data = []
this.data.push(0)
}
Heap.prototype.heappush = function (val, points = []) {
this.data.push([val,points])
this.data[0] += 1
this.up(this.data[0])
}
Heap.prototype.heappop = function () {
if(this.data[0] !== 1){
this.swap(1, this.data[0])
}
const res = this.data.pop()
this.data[0] -= 1
this.down()
return res
}
Heap.prototype.swap = function (a, b) {
let temp = this.data[a]
this.data[a] = this.data[b]
this.data[b] = temp
}
Heap.prototype.down = function (index = 1) {
if (index * 2 > this.data[0]) return
const left = 2 * index
const right = 2 * index + 1
let target = index
if (left <= this.data[0] && this.data[left][0] < this.data[target][0]) {
target = left
}
if (right <= this.data[0] && this.data[right][0] < this.data[target][0]) {
target = right
}
if (target !== index) {
this.swap(target, index)
this.down(target)
}
}
Heap.prototype.up = function (index) {
if (index < 2) return
const fatherIndex = Math.floor(index / 2)
if (this.data[index][0] < this.data[fatherIndex][0]) {
this.swap(index, fatherIndex)
this.up(fatherIndex)
}
}