力扣 407 接雨水2
题目可以自己去力扣看。
/**
* @param {number[][]} heightMap
* @return {number}
*/
var trapRainWater = function (heightMap) {
if (heightMap.length <= 2 || heightMap[0].length <= 2) {
return 0;
}
const n = heightMap.length
const m = heightMap[0].length
let vis = {}
let queue = new PriorityQueue()
let res = 0
// 把边缘点加入优先队列
for (let i = 0; i < n; i++) {
vis[i + ',' + 0] = true;
queue.add([heightMap[i][0], i, 0])
vis[i + ',' + (m - 1)] = true;
queue.add([heightMap[i][m - 1], i, m - 1])
}
for (let i = 1; i < m - 1; i++) {
vis[0 + ',' + i] = true;
queue.add([heightMap[0][i], 0, i])
vis[(n - 1) + ',' + i] = true;
queue.add([heightMap[n - 1][i], n - 1, i])
}
// 不断更新接水点
while (queue.size()) {
let [height, curN, curM] = queue.delete()
// 访问相邻点
let x = curN
let y = curM + 1
if (y < m) {
updateNode(x, y, height)
}
y = curM - 1
if (y >= 0) {
updateNode(x, y, height)
}
y = curM
x = curN - 1
if (x >= 0) {
updateNode(x, y, height)
}
x = curN + 1
if (x < n) {
updateNode(x, y, height)
}
}
return res;
// 更新节点信息,如果没访问过就把节点推入优先队列
function updateNode(x, y, height) {
if (!vis[x + ',' + y]) {
vis[x + ',' + y] = true
if (heightMap[x][y] < height) {
res += (height - heightMap[x][y])
}
queue.add([Math.max(height, heightMap[x][y]), x, y])
}
}
};
// 优先队列
class PriorityQueue {
constructor() {
this.arr = [];
}
shiftMinUp() { // 自底向上调整
const { arr } = this;
let i = arr.length - 1;
let j = ~~((i + 1) / 2) - 1;
let temp = arr[i];
while (j >= 0) {
if (temp[0] < arr[j][0]) {
arr[i] = arr[j];
} else {
break;
}
i = j;
j = j = ~~((j + 1) / 2) - 1;
}
arr[i] = temp;
}
shiftDownMin() { // 自顶向下调整
const { arr } = this;
if (!arr.length) {
return arr;
}
let i = 0;
let j = 2 * i + 1;
let temp = arr[0];
while (j < arr.length) {
if (j < arr.length - 1 && arr[j][0] > arr[j + 1][0]) {
j++;
}
if (temp[0] > arr[j][0]) {
arr[i] = arr[j];
} else {
break;
}
i = j;
j = j * 2 + 1;
}
arr[i] = temp;
}
add(num) { // 插入元素的时候在数组最后,也就是在叶子节点,需要往上调整位置
const { arr } = this;
arr.push(num);
this.shiftMinUp();
}
delete() { // 删除时把队尾放到队首,此时可以从上到下调整位置
const { arr } = this;
let d = arr[0];
arr[0] = arr[arr.length - 1];
arr.pop()
this.shiftDownMin();
return d;
}
size() {
return this.arr.length;
}
get() {
return this.arr[0];
}
}