当前位置: 首页 > news >正文

【DFS】二叉树中的深搜

目录

计算布尔二叉树的值

求根节点到叶节点数字之和(稍困难)

二叉树剪枝

验证二叉搜索树

二叉搜索树中第 K 小的元素

二叉树的所有路径

全排列

子集


深度优先遍历(DFS),是我们树或者图这样的数据结构中常用的一种遍历算法。这个算法会尽可能深的搜索树或者图的分支,直到一条路径上的所有结点都能被遍历完毕,然后回溯到上一层,继续找一条路遍历。

在二叉树中,常见的深度优先遍历为:前序遍历、中序遍历、后序遍历

因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅易理解而且代码简洁,并且前中后序三种遍历的唯一区别就是访问根节点的时机不同。

遍历是形式,目的是搜索。回溯与剪枝 本质就是深搜

计算布尔二叉树的值

2331. 计算布尔二叉树的值 - 力扣(LeetCode)

解法:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    public boolean evaluateTree(TreeNode root) {
        if (root.left == null)
            return root.val == 0 ? false : true;
        boolean left = evaluateTree(root.left);
        boolean right = evaluateTree(root.right);
        return root.val == 2 ? left | right : left & right;// 逻辑与 逻辑或
    }
}
求根节点到叶节点数字之和(稍困难)

129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

解法:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    public int sumNumbers(TreeNode root) {
        return dfs(root, 0);
    }

    public int dfs(TreeNode root, int preSum) {
        preSum = preSum * 10 + root.val;
        if (root.left == null && root.right == null) {
            return preSum;
        }
        int ret = 0;
        if (root.left != null)
            ret += dfs(root.left, preSum);
        if (root.right != null)
            ret += dfs(root.right, preSum);
        return ret;
    }
}
二叉树剪枝

814. 二叉树剪枝 - 力扣(LeetCode)

解法:通过决策树,抽象出递归的三个核心问题

后序遍历

  1. 函数头 Node* dfs( root )
  2. 函数体 
    1. 处理左子树
    2. 处理右子树
    3. 判断
  3. 递归出口 root==null,return null;
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    public TreeNode pruneTree(TreeNode root) {
        if (root == null)
            return root;
        root.left = pruneTree(root.left);
        root.right = pruneTree(root.right);
        if (root.left == null && root.right == null && root.val == 0)
            root = null;
        return root;
    }
}
验证二叉搜索树

98. 验证二叉搜索树 - 力扣(LeetCode)

二叉搜索树的中序遍历,是一个有序的序列

  1. 全局变量的优势
  2. 回溯
  3. 剪枝(加快搜索过程)

策略一:左子树是二叉搜索树;当前节点符合二叉搜索树的定义;右子树也是二叉搜索树

策略二:剪枝

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    long prev = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        if (root == null)
            return true;
        boolean left = isValidBST(root.left);// 左
        if (left == false)
            return false;// 剪枝
        boolean cur = false;
        if (root.val > prev)
            cur = true;// 中
        if (cur == false)
            return false;// 剪枝
        prev = root.val;
        boolean right = isValidBST(root.right);// 右
        return left && cur && right;
    }
}
二叉搜索树中第 K 小的元素

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

解法:两个全局变量+中序遍历(有序)+剪枝优化

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    int count = 0;
    int ret = 0;

    public int kthSmallest(TreeNode root, int k) {
        count = k;
        dfs(root);
        return ret;
    }

    void dfs(TreeNode root) {
        if (root == null || count == 0)
            return;// 判空+剪枝(count=0时直接返回)
        // 中序遍历
        dfs(root.left);// 左
        count--;
        if (count == 0) {// 中
            ret = root.val;
            return;
        }
        dfs(root.right);// 右
    }
}
二叉树的所有路径

257. 二叉树的所有路径 - 力扣(LeetCode)

全局变量

回溯->“恢复现场

剪枝

函数头:void dfs(root,path)

函数体:if(root==叶):;root≠叶:;

递归出口:if(root==null) return;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    List<String> ret;

    public List<String> binaryTreePaths(TreeNode root) {
        ret = new ArrayList<>();
        dfs(root, new StringBuffer());
        return ret;
    }

    void dfs(TreeNode root, StringBuffer _path) {
        StringBuffer path = new StringBuffer(_path);
        path.append(Integer.toString(root.val));
        if (root.left == null && root.right == null) {// 根节点
            ret.add(path.toString());// 返回该路径,给ret
            return;
        }
        path.append("->");
        if (root.left != null)
            dfs(root.left, path);// 剪枝
        if (root.right != null)
            dfs(root.right, path);// 剪枝

    }
}
全排列

46. 全排列 - 力扣(LeetCode)

解法:穷举(枚举)+  递归

  1. 画出决策树:越详细越好
  2. 设计代码
    1. 全局变量 int[][] ret; int[] path; bool[] check;(实现剪枝)
    2. dfs函数 - 仅需关心某个节点在干什么
    3. 细节:回溯(干掉path最后一个元素;修改check数组)
class Solution {
    // 设置全局变量
    List<List<Integer>> ret;
    List<Integer> path;
    boolean[] check;

    public List<List<Integer>> permute(int[] nums) {
        ret = new ArrayList<>();
        path = new ArrayList<>();
        check = new boolean[nums.length];
        dfs(nums);
        return ret;
    }

    public void dfs(int[] nums) {
        if (path.size() == nums.length) {
            ret.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (check[i] == false) {
                path.add(nums[i]);
                check[i] = true;
                dfs(nums);
                // 回溯-恢复现场
                check[i] = false;
                path.remove(path.size() - 1);
            }
        }
    }
}
子集

78. 子集 - 力扣(LeetCode)

叶节点即结果

  1. 决策树
  2. 设计代码
    1. 全局变量 int[ ] path; int[ ] ret;
    2. dfs(nums,i)
      1. 选:path+=nums[ i ],dfs(nums,i+1)
      2. 不选:dfs(nums,i+1)

细节:剪枝,回溯,递归出口

class Solution {
    // 设置全局变量
    List<List<Integer>> ret;
    List<Integer> path;

    public List<List<Integer>> subsets(int[] nums) {
        ret = new ArrayList<>();
        path = new ArrayList<>();
        dfs(nums, 0);
        return ret;
    }

    public void dfs(int[] nums, int pos) {
        ret.add(new ArrayList<>(path));
        for (int i = pos; i < nums.length; i++) {
            path.add(nums[i]);
            dfs(nums, i + 1);
            path.remove(path.size() - 1);// 回溯-恢复现场
        }
    }
}

相关文章:

  • 【实测闭坑】LazyGraphRAG利用本地ollama提供Embedding model服务和火山引擎的deepseek API构建本地知识库
  • 【自定义微信小程序拉下选择过滤组件】searchable-select
  • Spring Boot 整合 Elasticsearch:打造高性能全文检索实战
  • SQL优化记录
  • 【Go语言圣经3.6】
  • C++学习之redis
  • (C语言)指针与指针数组的使用教学(C语言基础教学)(指针教学)
  • 【算法百题】专题七_分治快排_专题八_分治归并
  • (hash表+vector 数位和相等数对的最大和)leetcode 2342
  • 遥感数据处理
  • 七、面向对象高级_设计模式
  • Visual Studio里的“公共语言运行时支持”各选项的作用是什么,分别适用于哪些场景?
  • 宇树与智元的崛起:机器人“灵魂”注入的技术密码
  • Mock接口编写教程-axios-mock-adapter(React)
  • 神聖的綫性代數速成例題6. 方陣行列式的性質、伴隨矩陣
  • Python驱动CATIA自动化建模:科赫雪花算法实现与工程应用
  • AI数字人短视频数字人口播源码核心技术解析与商业应用
  • 使用usb-cam包时填充摄像头参数话题
  • 第27周JavaSpringboot git初识
  • 【商城实战(30)】从0到1搭建商城数据分析功能,开启数据驱动增长引擎
  • 民生访谈|支持外贸企业拓内销,上海正抓紧制定便利措施
  • 南京航空航天大学启动扁平化改革:管理岗规模控制在20%,不再统一设科级机构
  • 安徽省公安厅原副厅长刘海石主动投案,正接受审查调查
  • 外交部亚洲司司长刘劲松向菲方严肃交涉
  • 卸任兰大校长后,严纯华院士重返北大作报告
  • 今年一季度全国社会物流总额达91万亿元,工业品比重超八成