一、题目描述:
你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
示例:
输入:[ [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
二、思路分析:
这道题很显然是很典型的深度优先遍历算法(DFS,Depth-First-Search),(当然也可以使用BFS,我们这里先不讨论)。对于这类题目,给的参数是个二维数组,然后让我们去查找里面符合条件元素的所有值,这个时候我们第一个要考虑的就是深度优先遍历了。虽然性能不一定是最好的,但是这种方法很大概率上可以算出答案。 深度优先遍历算法的核心思想是:穷尽所有的完整路径。解决的一般方法是:
- 我们先遍历数组找到符合条件的元素,然后以这些元素为中心递归遍历题目中符合条件的位置,题目中会有明显的限制条件,比如垂直水平位置,或者加上垂直方向,在遍历的时候对这些符合条件位置进行递归。
- 在递归的时候边界条件通常是二维数组的行头尾/列头尾,同时要注意在一个元素遍历完成之后需要及时的修改值,避免重复遍历
- 使用一个全局变量,将递归遍历的结果给保存起来,注意如果使用中间变量存储的时候每次遍历的时候要及时置空。
三、AC 代码:
这里晒一下我自己的代码,按照上面的规律来写,性能一般但是在面试的时候可以很快的得出结果
/**
* @param {number[][]} land
* @return {number[]}
*/
var pondSizes = function(land) {
let row = land.length;
let col = land[0].length;
let res = []
let temp = 0;
const direct = [[1,0],[-1,0],[0,1],[0,-1],[1,1],[-1,-1],[1,-1],[-1,1]]
const DFS = (land,i,j)=>{
if(i<0||j<0||i>=row||j>=col) return;
if(land[i][j] != 0) return;
land[i][j]=1;
temp++;
for(let m = 0;m<direct.length;m++){
DFS(land,i+direct[m][0],j+direct[m][1])
}
}
for(let i = 0;i<row;i++){
for(let j=0;j<col;j++){
if(land[i][j]==0){
DFS(land,i,j)
res.push(temp)
temp=0;
}
}
}
return res.sort()
};
四、总结:
经典的DFS算法题目通常都可以使用上面的思路来解答,可能存在的区别就是边界条件,所要查找的元素内容。
当然,DFS题目不止这一种类型,我们这里可以梳理一下:
- 我们需要递归查找的内容是二维数组,有的时候查找的内容是连续的,比如需要拼接字符串,这个时候我们遍历的时候需要保存一个状态,一般使用栈比较好,注意递归的时候及时出栈入栈
- 我们需要递归查找的是二叉树,这个时候其实是个递归查找,解题模版基本如下:
const DFS = (root){
if(!root) return ;
if(!root.left&&!root.right&&...){
return;
}
DFS(root.left);
DFS(root.right);
...
}
当然这里说的模版并不能用来解决所有的此类题目,但是在遇到这种题目的时候使用模版可以第一时间找到思路,避免没有头绪。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情