当前位置:网站首页 > 技术博客 > 正文

非连通图的深度优先遍历算法



深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

  1. 为了求得问题的解,先选择某一种可能情况向前探索;
  2. 在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;
  3. 如此反复进行,直至得到解或证明无解。
  1. 初始原点为v0,使用深度优先搜索,首先访问 v0 -> v1 -> v2 -> v5,到 v5 后面没有结点,则回溯到 v1 ,即最近的且连接有没访问结点的结点v1
  2. 此次从 v1 出发,访问 v1 -> v4 -> v6 -> v3,此时与v3相连的两个结点 v0 与 v6 都已经访问过,回溯到 v6 (v6 具有没访问过的结点);
  3. 此次从 v6 出发,访问 v6 -> v7,到 v7 后面没有结点,回溯;
  4. 一直回溯到源点 v0 ,没有没访问过的结点,程序结束。

注:下面图中箭头为回溯方向
在这里插入图片描述

C模板:

 

C++模板:

 

学算法当然要刷题领悟啦,不然就是我这种一看就会(只是背了下来),一写就废的菜鸡 ^ - ^
下面就让我们一起看看这个俗称不撞南墙不回头算法都有哪些例题!!!

1、排列问题

题目一:

设有n个整数的集合{1,2,…,n},从中取出任意r个数进行排列(1<=r<n<=10),试列出所有的排列。

示例:

输入:n = 4, r = 3
输出:
1 2 3
1 2 4
1 3 2
1 3 4
1 4 2
1 4 3
2 1 3
2 1 4
2 3 1
2 3 4
2 4 1
2 4 3
3 1 2
3 1 4
3 2 1
3 2 4
3 4 1
3 4 2
4 1 2
4 1 3
4 2 1
4 2 3
4 3 1
4 3 2
24

分析:

在这里某个元素按不同次序出现的组合应视为不同的排列。例如:1 2 3和2 1 3,元素均为1.2.3,只是排列顺序不同,因此应视为元素1.2.3的不同排列。

实现过程:

  1. 定义两个数组 a[] 与 book[] ,其中数组a保存每次的排列数据,数组book用来标记 i 这个数是否被访问;
  2. 初始化相关数据;
  3. 递归填数并判断第i个数填入是否合法:
    合法:填数,并判断是否已经到达环的终点。如果到达终点,打印结果;否则,继续填下一个数;
    不合法:选择下一种可能。

特别地,当n=r时,称为n的全排列。实现时只需把下面程序的终点改为cur==n即可。

AC代码:
 
题目二:

给定一个不含重复数字的数组 nums ,返回其所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:
分析:

具体分析与提交答案请点击题目,这里就不在一一赘述!!!

AC代码:
 
题目三:

【LeetCode每日一题】784. 字母大小写全排列 —— DFS算法(C/C++)

给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串。

返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。

示例 1:
示例 2:

提示:
1 <= s.length <= 12
s 由小写英文字母、大写英文字母和数字组成

分析:

若不明白 isdigit() 函数请看这篇:isdigit函数详解

AC代码:
 

2、组合问题

题目一:

你可以按 任何顺序 返回答案。

示例 :

输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

提示:
1 <= n <= 20
1 <= k <= n

分析:

具体思路与排序差不多,具体需要注意的是,这里某种数字组合的多种排列视为相同情况,因此需 “去重”
一种可行的方案是填数的时候:

  1. 如果当前填的是第一个数,则直接填入;
  2. 在 1 的基础上,后面填入的数都要比前面的数大,因此要进行大小的比较。如果不符合条件,则不能填入。这样既能保证每种组合中数是递增的,也能保证组合是按字典序输出的。
AC代码:
 

3、n皇后问题

题目一:

在这里插入图片描述

上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 33 个解。最后一行是解的总个数。

输入格式:

一行一个正整数 n,表示棋盘是 n×n 大小的。

输出格式:

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

示例:

输入:6
输出:
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

分析:

问题的关键在于如何判定某个皇后所在的行、列、斜线上是否有别的皇后;可以从矩阵的特点上找到规律,如果在同一行,则行号相同;如果在同一列上,则列号相同;如果同在/斜线上的行列值之和相同;如果同在\斜线上的行列值之差相同;从下图可验证:

在摆放皇后时,可以”按行摆放”(这样就保证了皇后不会横向攻击)。即:

(1)起点为 dfs(0),即从第0行开始摆放皇后,逐行进行。同时使用一维数组 map 保存第 cur 行的皇后摆放的列,也就是说每次尝试摆放皇后的位置坐标为 (cur, map[cur]);

(2)逐列遍历,若发现位置 (i, map[j]) 与位置 (cur, map[cur]) 在同一列 或 同一主对角线 或 同一副对角线上时,摆放失败,该方案”作废”,继续执行;

(3)若摆放成功,则 dfs(cur+1),表示继续摆放下一行,过程同上;

(4)当 cur=n,即n行皇后均摆放完成时,表示该方案可行,总方案数+1。

AC代码:
 

4、素数问题

素数问题有好多经典题型,例如素数环、素数和、和为素数等等;下面就来介绍几个经典例题,大家一起来学习吧。

题目一:

3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34

现在,要求你计算出和为素数共有多少种。

例如上例,只有一种的和为素数:3+7+19=29。

输入格式:

输出格式:
输出一个整数,表示种类数。

示例:

输入:
4 3
3 7 12 19
输出:
1

分析:

本题是 dfs 中的一个非常经典的问题——素数问题中的一个分支,总体思路同上,都是循环遍历加判断 cur == k ;与上面不同的地方在于本类问题需要判断素数,下面我介绍一个判断素数的方法:

  1. 0,1 直接返回 false;
  2. 循环从 2 开始,根号下 x 结束,若 x % i 为 0 ,说明 x 有除 1 和它本身的其他因数,返回 false ;
AC代码:

                            

  • 上一篇: tftp协议禁用
  • 下一篇: 测试cpu性能的工具
  • 版权声明


    相关文章:

  • tftp协议禁用2024-11-13 08:30:00
  • spring-security-oauth22024-11-13 08:30:00
  • xdisplay(‎App Store 上的“Splashtop Wired XDisplay HD– 显示器扩展与镜像”)2024-11-13 08:30:00
  • 微信虚拟定位免费版哪个软件好用2024-11-13 08:30:00
  • 电驴官方网站下载软件2024-11-13 08:30:00
  • 测试cpu性能的工具2024-11-13 08:30:00
  • linux usb设备2024-11-13 08:30:00
  • 计算机发展历程简介2024-11-13 08:30:00
  • 代码设计思路 示例2024-11-13 08:30:00
  • mq消息中间件有哪些2024-11-13 08:30:00