深度优先搜索原理与实践
概论深度优先搜索属于图算法的一种,是一个针对图和树的遍历算法,英文缩写为 DFS 即 Depth First Search。深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。一般用堆数据结构来辅助实现 DFS 算法。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。 基本步奏(1)对于下面的树而言,DFS 方法首先从根节点1开始,其搜索节点顺序是 1,2,3,4,5,6,7,8(假定左分枝和右分枝中优先选择左分枝)。 ?
![]() ?
(2)从 stack 中访问栈顶的点; ![]() (3)找出与此点邻接的且尚未遍历的点,进行标记,然后放入 stack 中,依次进行; ![]() ?
(4)如果此点没有尚未遍历的邻接点,则将此点从 stack 中弹出,再按照(3)依次进行; ![]() (5) 由于与节点 5 相连的的节点都被访问过了,于是5被弹出,查找与 4 相邻但没有被访问过的节点: ![]() (6)直到遍历完整个树,stack 里的元素都将弹出,最后栈为空,DFS 遍历完成。 ?
![]() (7)
![]() // 用于记录某个节点是否访问过 通过上面的示例,基本了解 dfs 使用。 通用框架其一般框架原理如下: dfs() { (到达终点状态) { ... 根据题意添加 ; } if(越界或不合法状态) ; if(特殊状态) 剪枝 ; (扩展方式) { (扩张方式所到达状态合法) { 修改操作; 根据题意添加 标记; dfs(); (还原标记); 是否加上还原标记根据题意 如果加上还原标记就是回溯法 } } } 通过这个 dfs 框架可以看出该方法主要有以下几个规律:
下面将结合几道算法题来加深对深度优先搜索算法的理解。 1、全排列问题:给定大于0的数字n,输出数字 1 ~ n 之间的全排列。 对于这道题目,有些人可能会好奇为啥这到题目可以使用 dfs 算法。对于全排列,其实可以通过树的形式来进行理解: ?可以发现就是一个 n 叉树,总共是 n 层,下面采用前面总结的规律来看看算法实现原理:
下面就是算法实现: // 调用入口,起始点 可以发现,代码还是很简单的。 ? 695. 岛屿的最大面积给定一个包含了一些 0 和 1 的非空二维数组?grid 。 一个?岛屿?是由一些相邻的?1?(代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设?grid 的四个边缘都被 0(代表水)包围着。 找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。) 示例 1: [[0,1,0],[0,0]]
对于上面这个给定矩阵应返回?6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。 示例 2: [[0,0]] 对于上面这个给定的矩阵,返回?0。 注意:?给定的矩阵grid?的长度和宽度都不超过 50。 ?对于这道题目还是采用之前的分析方式:
题目解答如下: class Solution { int maxAreaOfIsland([][] grid) { if (grid == null || grid.length <1 || grid[0].length<1) { return 0int rx = grid.length; int cy = grid[0].length; int max = 0; int x =0; x< rx; x++int y= 0;y<cy; y++) { if (grid[x][y]==1) { //只有节点等于1才调用,这里就可以算作是剪枝,算法的优化 int num = dfs(grid,x,y); max = Math.max(max,num); } } } max; } // 递归参数:节点位置x,y,二维数组 int dfs (int[][] grid,1)">int x,1)"> y){ ].length; 200. 岛屿数量给你一个由?'1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 示例 1: 输入: 11110 11010 11000 00000 输出: 1 示例?2: 输入: 11000 11000 00100 00011 输出: 3 解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。 可以发现,这道题目与前面的题目很类似,关于 dfs 规则这里就不在分析了,留给大家自己去分析。 题目解答如下: int numIslands(charnull || grid.length < 1 || grid[0].length<1int num = 0 // 起始点 int x =0;x<rx;x++int y =0;y<cy;y++) { 到这里,深度优先搜索的理论和实践就讲完了,相信看到这里的小伙伴应该也掌握了其算法的原理,以及如何去书写。 ? 参考文章?基本算法——深度优先搜索(DFS)和广度优先搜索(BFS) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |