深搜(二叉树剪枝)(3)

一.题目

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

二.思路讲解

2.1 审题

本题要求对一棵二叉树进行剪枝 ,其中每个节点的值只能是 01 。剪枝的规则是:如果一棵子树中所有节点的值都为 0 ,那么将这棵子树整个移除。换句话说,我们需要从叶子节点向上检查,如果某个节点及其所有后代都不包含 1,则将该节点置为 nullptr,使其父节点不再指向它。

2.2 子问题解决

对于二叉树的问题,我们通常采用后序遍历的方式,因为要先知道左右子树的情况,才能决定当前节点是否需要被剪掉。具体思路如下:

  • 首先,递归地处理左子树右子树,得到它们剪枝后的结果。这一步我们相信递归能正确完成。

  • 然后,检查当前节点:如果左子树剪枝后为空右子树剪枝后为空当前节点的值本身为 0 ,说明以当前节点为根的整棵子树都不包含 1,那么应该将当前节点删除,即返回 nullptr 给父节点。

  • 否则,当前节点需要保留,并连接上剪枝后的左右子树,然后返回当前节点。

通过这种方式,我们自底向上地完成了剪枝,且每个节点只需要访问一次。

2.3 递归终止条件

递归的终止条件是当节点为空(nullptr)时,直接返回 nullptr。因为空节点既没有值也不属于任何子树,作为递归的基础情况非常自然。

三.代码演示

cpp 复制代码
/**
 * 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) 
    {
        //1.终止条件
        if(root == nullptr)
            return nullptr;
        //2.子问题解决
        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        if(root->left == nullptr && root->right == nullptr && root->val == 0)
        {
            return nullptr;
        }
        return root;
    }
};

四.代码讲解

一、递归函数设计

我们定义递归函数 pruneTree(TreeNode* root) ,它的含义是:对以 root 为根的二叉树进行剪枝,并返回剪枝后新的根节点(可能为 nullptr)。剪枝规则是移除所有不包含 1 的子树。由于我们需要先知道左右子树的情况才能决定当前节点是否保留,因此采用后序遍历的方式。

二、递归终止条件

当当前节点为空(root == nullptr)时,直接返回 nullptr。这是递归的基础情况,因为空节点自然不需要剪枝,也没有任何值。

三、递归步骤分解

对于非空节点,按照以下步骤进行后序遍历:

  1. 递归处理左子树 调用 pruneTree(root->left) 对左子树进行剪枝,并将结果重新赋值给 root->left。这一步会移除左子树中所有全零子树,返回剪枝后的左子节点(可能为空)。我们相信递归能正确完成

  2. 递归处理右子树 同理,调用 pruneTree(root->right) 对右子树剪枝,结果赋给 root->right

  3. 判断当前节点是否需要被移除 在左右子树都处理完毕后,检查当前节点是否满足移除条件 :左子树为空、右子树为空、且当前节点的值为 0。如果三者同时成立,说明以当前节点为根的整棵子树都不包含 1,因此应该将当前节点移除,返回 nullptr 给父节点。

  4. 返回保留的节点 如果不满足移除条件,则当前节点需要保留,直接返回 root。此时它的左右子树已经过剪枝,结构正确。

四、关键细节
  • 后序遍历的必要性:只有先知道左右子树是否为空,才能判断当前节点是否应该被删除。这是由剪枝规则决定的。。

  • 指针更新 :通过 root->left = pruneTree(root->left) 的方式,将剪枝后的子树直接挂回当前节点,实现了原地修改。

  • 移除条件:注意条件是左右子树都为空且当前节点值为0,这意味着整棵子树都无1。如果当前节点值为1,即使左右为空也保留;如果某子树非空,说明该子树有1,当前节点也保留。

相关推荐
2401_868534786 小时前
RTOS之RT-Thread & Linux:线程/进程管理与调度核心差异分析
c++·python
wabs6666 小时前
关于图论【卡码网117.软件构建的思考】
数据结构·算法·软件构建·图论·卡码网
mifengxing6 小时前
LeetCode 41.缺失的第一个正数|Hard题O(n)+O(1)最优解法深度解析
java·算法·leetcode·排序算法
郝学胜-神的一滴7 小时前
Qt 高级编程 040:按钮悬浮弹出滑块弹窗的完整攻略
开发语言·c++·qt·软件工程·用户界面
Tongzhi20267 小时前
从部署到运维:通芝科技无感考勤一体机的全流程效率解析
运维·数据结构·科技·算法·贪心算法
Wang's Blog7 小时前
AI Agent白手起家30: 动态示例选择器之根据长度选择 Few Shot 示例
算法
oyguyteggytrrwwwrt9 小时前
自制交叉线路识别算法
算法
手写码匠9 小时前
华为云Flexus+DeepSeek征文|Dify 多智能体协同编排实战:R1 规划 + V3 执行,构建企业 Agent 团队
人工智能·深度学习·算法·aigc
晓天衡宇•评测社区10 小时前
FSR-Bench 前沿科学推理榜单发布:GPT-5.5 居首,“会推理”未必“能答对”
算法
程序喵大人11 小时前
【C++进阶】STL算法与函数对象 - 02 sort为什么需要随机访问迭代器
开发语言·c++·算法