持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
[面试题 16.19. 水域大小](leetcode.cn/problems/pa…)
你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
「示例1:」
输入:
[ [0,2,1,0],
[0,1,0,1],
[1,1,0,1],
[0,1,0,1]
]
输出: [1,2,4]
「提示:」
0 < len(land) <= 1000
0 < len(land[i]) <= 1000
解题思路
// 第一种
利用回溯来计算池塘的大小
1.我们发现一个水域,就以该水域为起点,计算该水域周围的水域数量
2.如果我们在水域周围发现新的水域,再以新的水域为起点,计算新的水域周围水域的数量,直到没有水域或者超出界限
3.我们每次计算过的水域,就将他置为陆地,防止再次计算造成死循环
最后将结果排序即可
// 第二种
广度优先搜索
代码实现
// 第一种
/**
* @param {number[][]} land
* @return {number[]}
*/
var pondSizes = function(land) {
const m = land.length, n = land[0].length
const res = [], steps = [[0, 1], [0, -1], [1, 0], [1, -1], [1, 1], [-1, 0], [-1, -1], [-1, 1]]
function getCount(x, y) {
let count = 1
for (const [dx, dy] of steps) {
const nx = x + dx, ny = y + dy
if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue
if (!land[nx][ny]) {
land[nx][ny] = 1
count += getCount(nx, ny)
}
}
return count
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (!land[i][j]) {
land[i][j] = 1
res.push(getCount(i, j))
}
}
}
return res.sort((a, b) => a - b)
};
// 第二种
/**
* @param {number[][]} land
* @return {number[]}
*/
var pondSizes = function(land) {
let res = [];
for (let r=0; r<land.length; r++) {
for (let c=0; c<land[0].length; c++) {
if (land[r][c] === 0) {
let q = [[r,c]];
let size = 0;
land[r][c] = -1;
while (q.length) {
let [curR, curC] = q.shift();
size += 1;
let rr = [curR-1, curR, curR+1];
let cc = [curC-1, curC, curC+1];
for (let nr of rr) {
for (let nc of cc) {
if (nr < land.length && nr >= 0) {
if (nc < land[0].length && nc >= 0) {
if (!(nr === curR && nc === curC) && land[nr][nc] === 0) {
land[nr][nc] = -1;
q.push([nr, nc]);
}
}
}
}
}
}
res.push(size);
}
}
}
res.sort((a,b) => a-b);
return res;
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;