深度优先搜索(DFS)的关键是解决"当下该如何做",下一步的做法和当下的做法是一样的。"当下如何做"一般是尝试每一种可能,用for循环遍历,对于每一种可能确定之后,继续走下一步,当前的剩余可能等到从下一步回退之后再处理。
dfs一般处理逻辑:
Dfs(当前这一步的处理逻辑)
{
1. 判断边界,是否已经一条道走到黑了:向上回退
2. 尝试当下的每一种可能
3. 确定一种可能之后,继续下一步 Dfs(下一步)
}
1.员工的重要性
https://leetcode-cn.com/problems/employee-importance/
思路:先把员工信息和员工id 用map 关联起来方便操作;
然后用dfs 深搜当前员工的subordinates 累加当前员工的importance和subordinates->importance
/*
// Definition for Employee.
class Employee {
public:
int id;
int importance;
vector<int> subordinates;
};
*/
class Solution {
public:
void dfs(unordered_map<int, Employee*>& info, int& sum, int id){
sum+=info[id]->importance;
for(auto e:info[id]->subordinates){
dfs(info,sum,e);
}
}
int getImportance(vector<Employee*> employees, int id) {
if(employees.empty())
return 0;
unordered_map<int,Employee*> info;
for(const auto e:employees)
info[e->id]=e;
int sum =0;
dfs(info,sum,id);
return sum;
}
};
2…岛屿的周长
https://leetcode-cn.com/problems/island-perimeter/
思路:首先如图可以发现一个格子能给整个岛屿提供的边长为 :4 - 这个格子上下左右中属于岛屿的各自的数量
然后使用dfs :找到一个格子(这里需要用一个二维数组used来记录是否访问过这个格子,避免重复处理)
这个格子属于岛屿则周长数++,不属于直接跳过;之后对这个格子上下左右继续进行深搜。
//这个题也可以遍历整个二维数组,这里用的深搜来写的
//这里用了一个flag 功能:判断如果还没找到第一个属于岛屿的格子还是需要dfs 找到第一个后flag=true 之后非岛屿的格子则不会在dfs访问。
bool flag =false;
int getcount(vector<vector<int>>& grid, int row, int col) {
int count = 0;
if (row < grid.size() && row >= 0 && col < grid[0].size() && col >= 0 && grid[row][col] == 1)
count++;
return count;
}
int nextPosition[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
void dfs(vector<vector<int>>& grid, vector<vector<int>>& used, int row, int col, int& sum)
{
used[row][col] =1;
if (grid[row][col] == 1) {
flag = true;
int num = getcount(grid, row + 1, col) + getcount(grid, row - 1, col) + getcount(grid, row, col + 1) + getcount(grid, row, col - 1);
sum += (4 - num);
}
for(int i=0;i<4;++i){
int nextrow=row+nextPosition[i][0];
int nextcol=col+nextPosition[i][1];
if(nextrow < grid.size() && nextrow >= 0 && nextcol < grid[0].size() && nextcol >= 0
&& used[nextrow][nextcol] == 0 ){
if( grid[nextrow][nextcol]!=0 ||!flag)
dfs(grid,used,nextrow,nextcol,sum);
}
}
}
int islandPerimeter(vector<vector<int>>& grid) {
int sum = 0;
vector<vector<int>> used(grid.size(), vector<int>(grid[0].size(), 0));
if(!grid.empty()) {
dfs(grid, used, 0, 0, sum);
}
return sum;
}
3.图像渲染
https://leetcode-cn.com/problems/flood-fill/
dfs思路:
1.处理当前坐标 染色 这里需要使用一个数组记录染过色的坐标避免重复处理 用oldColor记录下最初(sr,sc)的颜色
3. 然后dfs上下左右搜索(需要判断一下新的坐标是否越界,然后判断没有访问过且image[newsr][newsc]==oldColor 则dfs下一步)
int nextPosition[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; //用来更新搜索时的坐标
void dfs(vector<vector<int>>& image, vector<vector<int>>& used, int sr, int sc, int oldColor,int newColor) {
image[sr][sc]=newColor;
used[sr][sc]=1;
for(int i=0;i<4;++i){
int newsr=sr+nextPosition[i][0];
int newsc=sc+nextPosition[i][1];
if( newsr>=0 &&newsr<image.size() &&newsc>=0 &&newsc<image[0].size()
&& used[newsr][newsc]==0 && image[newsr][newsc]==oldColor)
dfs(image,used,newsr,newsc,oldColor,newColor);
}
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
vector<vector<int> > used(image.size(), vector<int>(image[0].size(), 0));
dfs(image, used, sr, sc,image[sr][sc],newColor);
return image;
}