「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。
每日刷题第39天 2021.02.04
1765.地图中的最高点
- leetcode原题链接:leetcode-cn.com/problems/ma…
- 难度:中等
- 方法:广度优先遍历(bfs)
题目
-
给你一个大小为 m x n 的整数矩阵 isWater ,它代表了一个由 陆地 和 水域 单元格组成的地图。
-
如果
isWater[i][j] == 0 ,格子 (i, j)是一个 陆地 格子。 -
如果
isWater[i][j] == 1 ,格子 (i, j)是一个 水域 格子。 -
你需要按照如下规则给每个单元格安排高度:
-
每个格子的高度都必须是非负的。
-
如果一个格子是是 水域 ,那么它的高度必须为 0 。
-
任意相邻的格子高度差 至多 为 1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边)
-
找到一种安排高度的方案,使得矩阵中的最高高度值最大 。
-
请你返回一个大小为
m x n的整数矩阵height,其中height[i][j] 是格子 (i, j)的高度。如果有多种解法,请返回任意一个 。
示例
- 示例1
输入:isWater = [[0,1],[0,0]]
输出:[[1,0],[2,1]]
解释:上图展示了给各个格子安排的高度。
蓝色格子是水域格,绿色格子是陆地格。
- 示例2
输入:isWater = [[0,0,1],[1,0,0],[0,0,0]]
输出:[[1,1,0],[0,1,1],[1,2,2]]
解释:所有安排方案中,最高可行高度为 2 。
任意安排方案中,只要最高高度为 2 且符合上述规则的,都为可行方案。
提示
- m == isWater.length
- n == isWater[i].length
- 1 <= m, n <= 1000
- isWater[i][j] 要么是 0 ,要么是 1 。
- 至少有 1 个水域格子。
注意⚠️
- 数组的
shift()方法,从头移除元素,复杂度为o(n),放在循环中每次执行,可能会超时。 - 改进方法:将每次需要从队列头部弹出的操作,单独开一个栈来进行,使用栈的
pop\push方法,可以有效的降低时间复杂度。
解法
- 回顾二叉树的bfs广度优先遍历,显示遍历第一层,再接着遍历第二层。
- 放到本题,水域为0层,四周的为1层,依次往后类推。
- 第一步:将所有的水域节点放入到队列中,
step = 0 - 第二步:声明
visited数组,记录当前节点是否已经遍历过,遍历过的节点就不需要再加入到队列中。注:visited数组,不能使用map集合来存储,其实也没有必要。因为map集合的key为数组时,调用的时候,不能成功。- 举例:
map(1) => ([0,1],1),使用map.get([0,1])无效,始终输出false
- 举例:
- 第三步:声明
height数组,记录陆地对应的高度。 - 第三步:书写
bfs的执行过程(可参考模版),其中弹出的数,会被删除。当弹出的数的四个方向的数都被放入队列中,同时需要标记visited数组值为1,因为已经进入过队列中。
var highestPeak = function(isWater) {
// 使用bfs
// 遍历出来,第一轮需要找的数
let queue = [];
let m = isWater.length;
let n = isWater[0].length;
let height = new Array(m);
let visited = new Array(m);
for(let i = 0; i < m; i++) {
height[i] = new Array(n);
visited[i] = new Array(n).fill(0);
}
for(let i = 0; i < m; i++) {
for(let j = 0; j < n; j++) {
if(isWater[i][j] == 1){
queue.push([i,j]);
height[i][j] = 0;
visited[i][j] = 1;
}
}
}
// 将水域全部存储进去,为第0层,后续遍历第1层,依次往后
let step = 0;
let x,y;
let next = [];
while(queue.length) {
let lenQ = queue.length;
next = [];
for(let i = 0; i < lenQ; i++) {
// 超时会T,需要给每一层单独开一个栈来进行存储,需要使用pop和push,因为shift的复杂度是o(n)
// let node = queue.shift();
let node = queue.pop();
// 上(x - 1,y)
x = node[0];
y = node[1];
height[x][y] = step;
if(x > 0 && !visited[x - 1][y]){
next.push([x - 1, y]);
visited[x - 1][y] = 1;
}
if(x < m - 1 && !visited[x + 1][y]) {
// 下(x + 1,y)
next.push([x + 1, y]);
visited[x + 1][y] = 1;
}
if(y > 0 && !visited[x][y - 1]) {
// 左(x,y - 1)
next.push([x,y - 1]);
visited[x][y - 1] = 1;
}
if(y < n - 1 && !visited[x][y + 1]) {
// 右(x,y + 1)
next.push([x,y + 1]);
visited[x][y + 1] = 1;
}
}
step++;
queue = next;
}
return height;
};