LeetCode算法题回顾——DFS深度优先搜索

  1. BFS和DFS很重要,是许多算法题的基础
  2. 应用范围:图 or 树。
  3. 求解问题类型:可达性问题(遍历的节点都是从初始节点可达的)
  4. 中心思想:不撞南墙不回头(所以终止条件“南墙”的设置很重要)

目录

1. 图/树 简述

2. DFS

dfs程序实现tips

递归代码框架

3. leetcode实例——medium

200. 岛屿的个数 &  46. 全排列 & 17. 电话号码的字母组合   


1. 图/树 简述

首先我们简单介绍一下图和树

  • 图(graph)表示物件与物件之间的关系的方法,一个图是由顶点(或称结点,vertex)和连接这些顶点的线(边,edge)组成的
LeetCode算法题回顾——DFS深度优先搜索_第1张图片 该图汇总有6个点,8条边,其中1号vertex有一条边指向自己
  • 树,大家应该很熟悉了(二叉树的题目也做了不少)N个点,N-1条边(只会有一条边指向自己,根节点没有所以是N-1).
LeetCode算法题回顾——DFS深度优先搜索_第2张图片 图像自 https://blog.csdn.net/fengyibande/article/details/80472190
  •  图中的DFS示例
LeetCode算法题回顾——DFS深度优先搜索_第3张图片

DFS搜索步骤:

从1开始(任意选择一个节点,这里选2)

1→2→3→4→6(到达尾端,返回4节点的另一个选择5)

6→5(全部遍历,end)

path: 1→2→3→4→6→5(不唯一)

(DFS像不像走迷宫?一条路走到黑不行我们再回到上一个起点寻找其他路)

LeetCode算法题回顾——DFS深度优先搜索_第4张图片

1→12→4→31→52→5→30→3→6

在二叉树中,是不是就像二叉树的先序遍历


2. DFS

Depth-First-Search/深度优先搜索算法(DFS)是一种用于遍历或搜索树或图的算法。

沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。 

核心步骤:搜索——终止——回溯——搜索——直到找到解/遍历全部节点

dfs程序实现tips

  • :用栈来保存当前节点信息,当遍历新节点返回时能够继续遍历当前节点。可以使用递归栈。
  • 访问标记:需要对已经遍历过的节点进行标记。(BFS同)

递归代码框架

  /*
该框架来自参考博客2
该DFS 框架以2D 坐标范围为例,来体现DFS 算法的实现思想。
*/
#include
#include
#include
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int map[maxn][maxn]; // 坐标范围
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向

bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
    if(!vst[x][y] && ...) // 满足条件
        return 1;
    else // 与约束条件冲突
        return 0;
}

void dfs(int x,int y)
{
    vst[x][y]=1; // 标记该节点被访问过
    if(map[x][y]==G) // 出现目标态G
    {
        ...... // 做相应处理
    return;
    }
    for(int i=0;i<4;i++)
    {
        if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点
        dfs(x+dir[i][0],y+dir[i][1]);
    }
    return; // 没有下层搜索节点,回溯
}
int main()
{
    ......
    return 0;
}

3. leetcode实例——medium

这里我们对如下三道题进行详细讲解,剩下题目欢迎读者执行操刀实战。

200. 岛屿的个数()

给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。

输入:     输入:
11110     11000
11010     11000
11000     00100
00000     00011

输出: 1   输出:3
  • 步骤:
  1. 标记当前搜索位置已被搜索(标记当前位置的mark数组为1)
  2. 按照方向数组的4个方向,拓展4个新位置newx newy
  3. 若新位置不在地图范围内,忽略
  4. 若新位置未曾到达过,(继续走迷宫)继续DFS该位置
LeetCode算法题回顾——DFS深度优先搜索_第5张图片 算法图示,来自参考博客1

 

(ps:之前做的时候用了一个标记数组,结果竟然超时了,后来改用直接更改原数组的值来进行标记)

  • 上代码 O(mn)time
class Solution {
public:
    int numIslands(vector>& grid) {
        if(grid.empty()) return 0;
        int result = 0;
        for(int i=0;i> &grid ,int x,int y){
        if(x>=0 && y>=0 && x

----------------------------------------------------------------

46. 全排列

class Solution {
public:
    vector> permute(vector& num) {
        vector> res;
        vector out, visited(num.size(), 0);
        permuteDFS(num, 0, visited, out, res);
        return res;
    }
    void permuteDFS(vector& num, int level, vector& visited, vector& out, vector>& res) {
        if (level == num.size()) {res.push_back(out); return;}
        for (int i = 0; i < num.size(); ++i) {
            if (visited[i] == 1) continue;
            visited[i] = 1;
            out.push_back(num[i]);
            permuteDFS(num, level + 1, visited, out, res);
            out.pop_back();
            visited[i] = 0;
        }
    }
};

 

-----------------------------------------------------------------

17. 电话号码的字母组合   

class Solution {
public:
    
    vector letterCombinations(string digits) {  
        vector strs;
        
        if( digits.length()  ==0) return strs;
        
        vector dic = {"", "", "abc","edf","ghi","jkl","mno","pqrs","tuv","wxyz"};
         
        dfs(digits, dic, 0,"", strs);
        
        return strs;
    }
     
    void dfs( string digits, vector dic, int level, string out,vector& strs ){
        if( level ==  digits.length() ) {
            strs.push_back(out);
            return;
        }
        string str = dic[digits[level]-'0'];
        
        for(int i=0; i

 

----------------------------------------------------------------

其他相关题目(点击即可访问):

130. 被围绕的区域

695. 岛屿的最大面积

574. 朋友圈

47. 全排列2

 


参考博文: 

LeetCode笔记 by cnwangzhou

【DFS】深度优先搜索递归方式讲解  by  I'mInLove

算法录 之 BFS和DFS by WhyWhy

 

 

 

 

 

你可能感兴趣的:(Leetcode)