什么是深度优先搜索?
???深度优先搜索(DFS)属于图算法的一种,类似于树的前序遍历,是树的前序遍历的推广。过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
??关于树的前序遍历可以参考上一篇博文:二叉树的遍历
深度优先搜索的过程
- 从图中某个顶点v出发,访问顶点v
- 找出刚访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
- 返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。
- 重复此步骤(2)和(3),直至图中所有顶点均被访问过,访问结束。
??用图表示一下:(蓝色实线表示访问下一个未被访问邻接点,红色虚线表示回溯,路线旁的数字表示访问的顺序)
??所以搜索结果为: v1 v2 v4 v8 v5 v3 v6 v7 (深度优先搜索的结果不是唯一的,因为每个邻接点大于1的节点在访问该节点的邻接点时的顺序不唯一)
深度优先搜索题目:
力扣 剑指offer12.矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 “ABCCED”(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
? 这道题使用深度优先搜索,先朝一个方向搜到底,在回溯至上一个节点,选择另一条满足条件的路线,直至找出结果。
递归参数: 当前元素在board中的索引值 i 和 j ,当前目标字符在 word 中的索引 k。
终止条件:
? 1.返回false:行或列索引越界 或 当前矩阵元素与目标字符不同 或当前矩阵元素已经访问过。
? 2.返回true:k = word.length - 1, 表示字符串word全部匹配
递推工作:
? 1.声明一个和board数组同样空间大小的辅助数组,全部赋值为false,代表全部未被访问,用来判断当前矩阵元素是否被访问过,访问的时候改为true,当前层dfs结束回溯时改回false,防止不能回溯。
? 2.搜索下一单元格:朝当前元素的上或 右 或 下 或 左四个方向开始下层dfs,循环步骤 1。
返回值: 返回布尔值ans,代表是否搜索到目标字符串word。
代码实现:
var exist = function(board, word) {
let ans = false
const row = board.length
const col = board[0].length
const end = word.length-1
const visited = new Array(row).fill(0).map(() => new Array(col).fill(false))
const ways = [[-1,0], [0,1], [1,0], [0,-1]]
const overBoarder = (i, j) => {
return i < 0 || i >= row || j<0 || j >= col
}
const dfs = (i, j, k) => {
if(k > end || ans){
return
}
if(k === end){
return ans = true
}
for(const way of ways){
let [si, sj] = way
const ni = i+si
const nj = j+sj
if(overBoarder(ni, nj)){
continue
}
if(board[ni][nj] !== word[k+1]){
continue
}
if(visited[ni][nj] == true){
continue
}
visited[ni][nj] = true
dfs(ni, nj, k+1)
visited[ni][nj] = false
}
}
outer: for(let i = 0; i < row ; i++){
for(let j = 0; j < col ; j++){
if(ans){
break outer;
}
if(board[i][j] == word[0]){
visited[i][j] = true
dfs(i, j, 0)
visited[i][j] = false
}
}
}
return ans
};
|