首页 > 编程语言 >【算法】二叉树中的 DFS

【算法】二叉树中的 DFS

时间:2024-09-28 09:22:59浏览次数:12  
标签:right TreeNode val nullptr DFS 算法 二叉树 root left

 【ps】本篇有 6 道 leetcode OJ。 

目录

一、算法简介

二、相关例题

1)计算布尔二叉树的值

.1- 题目解析

.2- 代码编写

2)求根节点到叶节点数字之和

.1- 题目解析

.2- 代码编写

3)二叉树剪枝

.1- 题目解析

.2- 代码编写

4)验证二叉搜索树

.1- 题目解析

.2- 代码编写

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

.1- 题目解析

.2- 代码编写

6)二叉树的所有路径

.1- 题目解析

.2- 代码编写


一、算法简介

        二叉树是一种经典的树结构,是节点的一个有限集合(该集合为空,或由一个根节点加上两棵别称为左子树和右子树的二叉树组成)。

         二叉树中又有一些特别的类型,例如二叉搜索树、红黑树等。其中,二叉搜索树又称二叉排序树,是一种 key 搜索模型它或是一棵空树,亦或是具有以下性质的二叉树:

  • 若根的左子树不为空,则左子树上所有节点的值都小于根节点的值;
  • 若根的右子树不为空,则右子树上所有节点的值都大于根节点的值;
  • 根的左右子树也分别为二叉搜索树。

         二叉树中最常见的操作就是遍历整棵树,例如:

  • 前序遍历:根->左子树->右子树。
  • 中序遍历:左子树->根->右子树。
  • 后序遍历:左子树->右子树->根。
  • 层序遍历:根->下一层叶子节点->下下一层叶子节点...(一般用 BFS 实现)

        遍历整棵树的过程,一般通过 DFS 来实现,且二叉树的题型最能展现 DFS 的特性。

        DFS(深度优先搜索)是树或图这样的数据结构中常⽤的⼀种遍历算法,主要通过递归来实现。这个算法会尽可能深地搜索树或图中的分⽀,直到⼀条路径上的所有节点都被遍历完毕,然后再回溯到上⼀层,继续找另⼀条路遍历。

         在⼆叉树中,树的定义本⾝就是递归定义,因此采⽤ DFS 的⽅法去实现树的前序遍历、中序遍历、后序遍历,不仅容易理解⽽且代码很简洁。前中后序三种遍历的唯⼀区别就是访问根节点的时机不同,在做题的时候,选择⼀个适当的遍历顺序,对于算法的理解是⾮常有帮助的。

二、相关例题

1)计算布尔二叉树的值

2331. 计算布尔二叉树的值

.1- 题目解析

        整体地来看一棵树的话,题目就是要求根据根的运算符来求左孩子和右孩子的运算结果,而要求得根的运算结果,就要先知道整棵左子树的结果和整棵右子树的结果,由此,这个运算的过程其实是一个后序遍历,那么,我们对整棵树通过 DFS 进行一次后序遍历即可。

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool evaluateTree(TreeNode* root) {
        if(root->left==nullptr)return root->val==0 ? false : true;
        bool l=evaluateTree(root->left);
        bool r=evaluateTree(root->right);
        bool ret=false;
        if(root->val==2)ret=l|r;
        else ret=l&r;
        return ret;
        }
};

2)求根节点到叶节点数字之和

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

.1- 题目解析

        与上道题不同的是,本题是前序遍历。

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        return dfs(root,0);
    }
    int dfs(TreeNode* root,int presum)
    {
        presum=presum*10+root->val;
        if(root->left==nullptr && root->right==nullptr)return presum;
        int ret=0;
        if(root->left)ret+=dfs(root->left,presum);
        if(root->right)ret+=dfs(root->right,presum);
        return ret;
    }
};

3)二叉树剪枝

814. 二叉树剪枝

.1- 题目解析

        要删除二叉树中值为 0 的叶子节点,就要先删除左子树中的,再删除右子树,最后如果左子树和右子树都被删除了且根也是 0,那就把根也删除。也就是说,这其实是一个后序遍历的过程,而要删除值为 0 的叶子节点,只需将该节点置为空即可。

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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)
        {
            root=nullptr;
        }
        return root;
    }
};

4)验证二叉搜索树

98. 验证二叉搜索树

.1- 题目解析

【Tips】二叉搜索树的中序遍历的结果,一定是一个升序序列。

        一颗二叉树要是二叉搜索树,那么根节点的左子树得是二叉搜索树,右子树也得是二叉搜索树。那么,我们可以通过中序遍历,先验证左子树是否是二叉搜索树,再将左孩子与根进行比较,然后再验证右子树是否是二叉搜索树,如果都满足二叉搜索树的性质,即左孩子 < 根 < 右孩子,那么整棵树就是一棵二叉搜索树。

        

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    long prev=LONG_MIN; //用全局变量存储上一个孩子节点的值
public:
    bool isValidBST(TreeNode* root) {
        if(root==nullptr)return true;

        bool left=isValidBST(root->left);//验证左子树
        if(!left)return false; //剪枝

        bool cur=false;
        if(root->val > prev)cur=true; //验证根与左孩子
        if(!cur)return false; //剪枝
        prev=root->val; //记录上一个孩子节点的值

        bool right=isValidBST(root->right);//验证右子树

        return left && right && cur;
    }
};

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

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

.1- 题目解析

        我们可以仿照上一道题,在中序遍历时用两个全局变量来分别记录已经遍历的次数和相应节点的值。

 

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    int count;
    int ret;
public:
    int kthSmallest(TreeNode* root, int k) {
        count=k;
        dfs(root);
        return ret;
    }
    void dfs(TreeNode* root)
    {
        if(root==nullptr || count==0)return; //剪枝
        dfs(root->left);
        count--;
        if(count==0)ret=root->val;
        dfs(root->right);
    }
};

6)二叉树的所有路径

257. 二叉树的所有路径

.1- 题目解析

        路径以字符串形式存储,从根节点开始前序遍历,每次遍历时将当前节点的值加⼊到路径中,如果该节点为叶子节点,将路径存储到结果中。否则,将 "->" 加⼊到路径中并递归遍历该节点的左右子树。 

 

.2- 代码编写

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    vector<string> ret;//存储路径
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        dfs(root,"");
        return ret;
    }
    void dfs(TreeNode* root,string path)//便于回溯时恢复现场
    {
        path+=to_string(root->val);
        if(!root->left && !root->right) //遍历到叶子节点,就停止添加节点值并记录当前结果
        {
            ret.push_back(path);
            return;
        }

        path+="->";

        if(root->left)dfs(root->left,path);
        if(root->right)dfs(root->right,path);
    }
};

标签:right,TreeNode,val,nullptr,DFS,算法,二叉树,root,left
From: https://blog.csdn.net/waluolandao/article/details/142448283

相关文章

  • 【开题报告】基于Springboot+vue基于推荐算法的高校就业管理系统(程序+源码+论文) 计算
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育的普及与就业市场的日益竞争,高校毕业生面临的就业压力日益增大。传统的高校就业管理方式往往依赖于线下招聘会、简历投递等低效手段,难以......
  • 基于冲突动态监测算法的健身房预约管理系统
    系统展示用户前台界面管理员后台界面系统背景  随着健身热潮的兴起,健身房管理面临着日益增长的会员需求与资源分配的挑战。传统的人工预约方式不仅效率低下,且容易出现时间冲突和资源浪费的情况。为了解决这一问题,基于冲突动态监测算法的健身房预约管理系统......
  • 开普勒优化算法:一种开普勒行星运动定律的元启发式算法
    目录1.摘要2.算法原理3.结果展示4.参考文献5.代码获取1.摘要这项研究介绍了开普勒优化算法(KOA),这是一种基于物理的新元启发式算法,灵感来源于开普勒行星运动定律。KOA通过模拟行星的位置和速度来寻找优化问题的解决方案,其中每个行星代表一个候选解,这些候选解会根据......
  • JAVA连接HDFS操作
    JAVA连接HDFS操作一、引言在大数据时代,Hadoop分布式文件系统(HDFS)扮演着重要的角色。对于Java开发者来说,掌握如何使用Java连接和操作HDFS是一项基本技能。本文将介绍如何通过Java代码连接HDFS,并执行一些基本的文件操作。二、连接HDFS1、第一步:添加依赖要使用Java操作HDF......
  • JAVA连接HDFS使用案例
    JAVA连接HDFS使用案例一、引言Hadoop分布式文件系统(HDFS)是大数据存储的基础。对于Java开发者来说,能够通过Java代码操作HDFS是处理大数据任务的关键技能。本文将通过几个简单的示例,展示如何使用Java连接HDFS并执行一些基本的文件操作。二、连接HDFS1、第一步:添加依赖在M......
  • 算法题:用队列实现一个链表
    下面是添加了注释的ListNode类和LinkedListQueue类,以帮助理解每个部分的功能和目的://定义链表节点类,用于存储队列中的元素classListNode{intval;//存储节点的值ListNodenext;//指向下一个节点的指针//构造函数,用于创建新的节点ListNod......
  • 嵌入式学习--数据结构+算法
    嵌入式学习--数据结构+算法数据结构1.1数据1.2逻辑结构1.3存储结构1)顺序存储结构2)链式存储结构1.4操作(数据的运算)算法2.1算法与程序2.2算法与数据结构2.3算法的特性2.4如何评价一个算法的好坏?2.5时间复杂度2.6空间复杂度数据结构数据的逻辑结构、存储结构、......
  • 互联网信息服务算法备案最详细操作指引
        为了服务开发者便捷地开展算法备案,小编整理出算法备案的申请操作指引,用以帮助开发者有序完成算法备案工作,共同维护安全有序的网络环境。    互联网信息服务算法备案系统(以下简称备案系统)的官方网址为https://beian.cac.gov.cn    依据《互联网信......
  • 【鸟类识别系统】计算机毕设项目+卷积神经网络算法+人工智能+深度学习+模型训练+Pytho
    一、介绍鸟类识别系统。本系统采用Python作为主要开发语言,通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型,然后进行模型的迭代训练,得到一个识别精度较高的模型,然后在保存为本地的H5格式文件。在使用Django开发Web网......
  • 【花朵识别系统】计算机毕设案例+卷积神经网络算法+人工智能+深度学习+Django网页界面
    一、介绍花朵识别系统。本系统采用Python作为主要编程语言,基于TensorFlow搭建ResNet50卷积神经网络算法模型,并基于前期收集到的5种常见的花朵数据集(向日葵、玫瑰、蒲公英、郁金香、菊花)进行处理后进行模型训练,最后得到一个识别精度较高的模型,然后保存为本地的h5格式文件,便......