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

【递归、搜索与回溯算法】二叉树中的深搜

目录

  • 前言
  • 算法原理和代码实现
    • 2331.计算bool二叉树的值
    • 129.求根节点到叶节点数字之和
    • 814.二叉树剪枝
    • 98.验证搜素二叉树
    • 230.二叉树中第K小的元素
    • 257.二叉树的所有路径

前言

本章内容是介绍关于二叉树中的dfs算法应用,它是续接上上一篇文章【递归、搜索与回溯算法】递归篇 的。
在⼆叉树中,常⻅的深度优先遍历为:前序遍历、中序遍历以及后序遍历。
因为树的定义本⾝就是递归定义,因此采⽤递归的⽅法去实现树的三种遍历不仅容易理解⽽且代码很简洁。并且前中后序三种遍历的唯⼀区别就是访问根节点的时机不同,在做题的时候,选择⼀个适当的遍历顺序,对于算法的理解是⾮常有帮助的。

算法原理和代码实现

2331.计算bool二叉树的值

在这里插入图片描述
在这里插入图片描述

算法原理:

从宏观角度看问题:
我们从根节点看,想知道这一层最终的结果是什么,得先知道左子树是true还是false,右子树是true还是false。在知道两者后,再根据根节点自己的值进行与或运算。

递归函数流程:
(1) 当前问题规模为 n=1 时,即叶⼦节点,直接返回当前节点值;
(2) 递归求得左右⼦节点的值;
(3) 通过判断当前节点的逻辑运算符,计算左右⼦节点值运算得出的结果。

代码实现:

class Solution 
{
public:
    bool evaluateTree(TreeNode* root) 
    {
        if(root->left == nullptr) return root->val == 0 ? false : true;

        bool left = evaluateTree(root->left);
        bool right = evaluateTree(root->right);
        
        return root->val == 2 ? left | right : left & right;
    }
};

129.求根节点到叶节点数字之和

在这里插入图片描述
在这里插入图片描述

算法原理:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
细节问题:

这里的递归出口是要在第一步执行完之后再判断,因为还要加上当前节点的值。

代码实现:

class Solution 
{
public:
    int sumNumbers(TreeNode* root) 
    {
        return dfs(root, 0);
    }

    int dfs(TreeNode* root, int prevsum)
    {
        prevsum = prevsum * 10 + root->val;
        // 递归出口
        if(root->left == nullptr && root->right == nullptr)
            return prevsum;
        // 函数体
        int ret = 0;
        if(root->left) ret += dfs(root->left, prevsum);
        if(root->right) ret += dfs(root->right, prevsum);
        return ret;
    }
};

814.二叉树剪枝

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法原理:

我们可以采用后序遍历的方式来解决这个问题。在后序遍历中,我们先处理左⼦树,然后处理右⼦树,最后再处理当前节点。在处理当前节点时,我们可以判断其是否为叶⼦节点且其值是否为0,如果满⾜条件,我们可以删除当前节点。
算法流程:
1.递归出口:当传入节点为空时,不做任何处理;
2.递归处理左⼦树;
3.递归处理右⼦树;
4.处理当前节点:判断该节点是否为叶子节点(即左右子节点均被删除,当前节点成为叶子节点),并且节点的值为 0:
a. 如果是,就删除掉;
b. 如果不是,就不做任何处理。

在这里插入图片描述

代码实现:

class Solution 
{
public:
    TreeNode* pruneTree(TreeNode* root) 
    {
        if(root == nullptr) return nullptr;

        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        if(root->left == nullptr && root->right == nullptr && root->val == 0)
        {
            delete root; // 防止内存泄漏
            root = nullptr;
        }
        return root;
    }
};

98.验证搜素二叉树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法原理:

根据"二叉搜索树的中序遍历是有序序列"这一特点入手。
我们可以定义一个全局变量,它的作用是:在中序遍历的过程中,保存上一个节点值,用于和下一个节点值进行比较

在中序遍历的过程中也有两种策略:
策略1:递归中不用剪枝(有点暴力)
a. 左子树是二叉搜索树?
b. 当前结点符合二叉搜索树的定义?
c. 右子树也是二叉搜索树?
再根据这三者的结果,判断当前树是否满足,返回给上一层。
策略2:递归中用剪枝
当发现有一棵子树不是二叉搜索树时,那就不用再递归判断另一棵子树了,整颗树已经不满足了。
在这里插入图片描述

策略1代码实现:

class Solution 
{
    long prev = LONG_MIN;
public:
    bool isValidBST(TreeNode* root) 
    {
        // 思路:根据中序遍历
        if(root == nullptr) return true;
        
        // 判断左右子树
        bool left = isValidBST(root->left);
        
        // 判断当前节点
        bool cur = false;
        if(root->val > prev)
            cur = true;
        
        prev = root->val;
        bool right = isValidBST(root->right);
        
        return left && right && cur;
    }
};

策略2代码实现:

class Solution 
{
    long prev = LONG_MIN;
public:
    bool isValidBST(TreeNode* root) 
    {
        // 思路:根据中序遍历
        if(root == nullptr) return true;
        
        // 判断左右子树
        bool left = isValidBST(root->left);
        // 剪枝
        if(left == false) return false;
        
        // 判断当前节点
        bool cur = false;
        if(root->val > prev)
            cur = true;
        // 剪枝
        if(cur == false) return false;
        
        prev = root->val;
        bool right = isValidBST(root->right);
        
        return left && right && cur;
    }
};

230.二叉树中第K小的元素

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法原理:

这道题也使用"二叉搜索树的中序遍历是有序序列"这一特点。
定义两个全局变量:
1是count用于计数:当count等于0时,当前节点值就是要返回的值。
2是ret用于存最终结果。
在这里插入图片描述

class Solution 
{
    int cnt; // 计数
    int ret; // 最终结果
public:
    int kthSmallest(TreeNode* root, int k) 
    {
        cnt = k;
        dfs(root);
        return ret;
    }

    void dfs(TreeNode* root)
    {
        // 递归出口+剪枝
        if(root == nullptr || cnt == 0) return;

        dfs(root->left);
        cnt--;
        if(cnt == 0) ret = root->val;
        dfs(root->right);
    }
};

257.二叉树的所有路径

在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/461822.html

相关文章:

  • PostgreSQL对称between比较运算
  • 多层设计模式:可否设计各层之间公用的数据定义模块?
  • 网络安全 | 信息安全管理体系(ISMS)认证与实施
  • 【网络】什么是路由协议(Routing Protocols)?常见的路由协议包括RIP、OSPF、EIGRP和BGP
  • 46. Three.js案例-创建颜色不断变化的立方体模型
  • 数字PWM直流调速系统设计(论文+源码)
  • RACI矩阵在项目管理中的应用:优化任务管理
  • Kafka配置公网或NLB访问(TCP代理)
  • Github 2024-12-31Python开源项目日报Top8
  • 两种分类代码:独热编码与标签编码
  • 人工智能在SEO中的应用与关键词优化策略
  • 目标检测之DINO详解
  • android 外挂modem模块实现Telephony相关功能(上网,发短信,打电话)
  • R中单细胞RNA-seq分析教程 (7)
  • 【Java项目】基于SpringBoot的【校园新闻网站】
  • 【Goland】怎么执行 go mod download
  • wire单总线通信
  • MySQL数据库笔记——多版本并发控制MVCC
  • 基于Java+Springboot+Vue开发的旅游景区管理系统,实习作品
  • LeetCode -Hot100 - 42. 接雨水
  • HTML5 评分星级组件
  • 【Pytorch实用教程】循环神经网络中使用dropout需要注意的问题
  • [江科大STM32] 第五集快速建立STM32工程模板——笔记
  • Spring-kafka快速Demo示例
  • css实现图片填充文字
  • MySQL数据库——多版本并发控制MVCC