什么是深度优先搜索
深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。其过程简单来说就是对每一个可能的分支深入到不能再深入位置,而且每个节点只能访问一次。
算法题应用场景
1.二叉树有关问题
2.需要从根节点遍历到末尾子节点
3.遍历图
常见题型
深度优先搜索的二叉树模板
// 深度优先搜索模板function dfsSearch() {// 初始化当前结果let start, currentResult// 递归函数let dfs = function (node, currentResult) {if (!node) { return null }// 更新当前结果currentResult// 若到达末尾叶子节点,进行最优结果更新if (node.left == null && node.right == null) {// 更新最优结果}// 左右子树递归dfs(node.left, currentResult)dfs(node.right, currentResult)}dfs(root, start)return currentResult}
判断是否是二叉搜索树
二叉树的中序遍历正好满足二叉搜索树的从小到大的排列规则
const helper = (root, lower, upper) => {if (root === null) {return true;}if (root.val <= lower || root.val >= upper) {return false;}return helper(root.left, lower, root.val) && helper(root.right, root.val, upper);}var isValidBST = function(root) {return helper(root, -Infinity, Infinity);};
对无向图的深度优先搜索
- 获取二维数组的长宽
- 遍历并添加边界条件递归调用DFS函数
-
机器人行走范围
对无向图的深度优先搜索模板(岛屿数量)
function get(arr) {// 通常输入的数组都是二维数组let m = arr.lengthlet n = arr[0].lengthlet count = 0function dfs(i, j) {// 跳出递归的边界条件if (i < 0 || j < 0 || i >= m || j >= n) return// 按照题中所给的要求递归遍历无向图dfs(i - 1, j) || dfs(i + 1, j) || dfs(i, j - 1) || dfs(i, j + 1)}for (let i = 0; i < m; i++) {for (let j = 0; j < n; j++) {// 符合题目的条件添加进结果或者计数if (arr[i][j] == 1) {// 更细最新结果count++dfs(i, j)}}}return count}
图像渲染

var floodFill = function (image, sr, sc, newColor) {let m = image.lengthlet n = image[0].lengthlet oldColor = image[sr][sc]if (newColor == oldColor) {return image}let dfs = function (i, j) {if (i < 0 || j < 0 || i >= m || j >= n || image[i][j] !== oldColor) {return}image[i][j] = newColordfs(i + 1, j) || dfs(i, j + 1) || dfs(i, j - 1) || dfs(i - 1, j)}dfs(sr, sc)return image};
深拷贝的深度优先搜索
不需要创建函数的DFS
路径总和
:::tips 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。 :::
:::tips
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
:::
:::tips
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 —> 2): 和为 3
(1 —> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
:::
:::tips
输入:root = [], targetSum = 0 输出:false 解释:由于树是空的,所以不存在根节点到叶子节点的路径。
:::

var hasPathSum = function(root, targetSum) {if(root === null) {return false}// 搜到叶子节点,则判断当前节点值是否等于目标值if(root.left === null && root.right === null) {return root.val === targetSum}// 还没搜到叶子节点,则进行 目标值-当前节点值,并继续往下搜return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val)};
路径总和ii
输出全部满足的路径数组
/*** @param {TreeNode} root* @param {number} targetSum* @return {number[][]}*/var pathSum = function (root, targetSum) {let res = [];let path = [];const dfs = (root, targetSum) => {// 如果节点为空则不需要再递归了if (root == null) {return;}// 把当前节点的值加入路径中path.push(root.val);// 由于路径中加入了当前节点,那目标值就少了targetSum -= root.val;if (root.left == null && root.right == null && targetSum == 0) {// 如果到达叶子节点 并且目标值满足res.push(path.slice());// res.push(path.concat());}dfs(root.left, targetSum);dfs(root.right, targetSum);// 左右子节点都递归完了,把当前节点从路径中删除,可走下一条路径path.pop();};dfs(root, targetSum);return res;};
路径总和iii

var sumNumbers = function (root) {return dfs(root, 0)};let dfs = function (root, prevSum) {if (!root) {return 0}let sum = prevSum * 10 + root.valif (!root.left && !root.right) {return sum}return dfs(root.left, sum) + dfs(root.right, sum)}
判断两个二叉树是否相等
var isSameTree = function(p, q) {if(!p && !q)return true;if(!p || !q)return false;if(p.val != q.val)return false;return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);}
单词搜索


var exist = function(board, word) {const W = board.length;const H = board[0].lengthconst K = word.length//搜索的方向const dirs = [[0, -1], [1, 0],[0, 1],[-1, 0]]function helper(i, j, k) {if (k>=K) return trueif (i >= W || j >= H || i < 0 || j < 0) return falseif (board[i][j] !== word[k]) return falseboard[i][j]='*'for (let [x,y] of dirs) {if(helper(i+x,j+y,k+1)) return true}board[i][j]=word[k]return false}for (let i = 0; i < W; i++) {for (let j = 0; j < H; j++) {if (helper(i,j,0)) return true}}return false};
