leetcode
leetcode 2951 ~ 3000
二叉树剪枝

二叉树剪枝

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 22 ms, 内存: 16.0 MB


/*
 * 思路:使用递归方法遍历二叉树,从叶子节点开始检查并删除值为0的节点。
 * 如果一个节点的所有子树均为0,那么删除该节点。
 * 注意:Java Stream不适用于这种操作,递归更为直接和合适。
 */
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    public TreeNode pruneTree(TreeNode root) {
        if (root == null) return null;
        root.left = pruneTree(root.left);
        root.right = pruneTree(root.right);
        if (root.val == 0 && root.left == null && root.right == null) {
            return null;
        }
        return root;
    }
}

解释

方法:

本题解采用递归方法来解决问题。递归函数 `pruneTree` 检查每个节点,如果一个节点的值为 0 并且它的左右子树也都被剪枝后不存在任何节点(即左右子节点都返回了 None),那么这个节点也应该被剪掉(返回 None)。递归首先处理左右子树,然后处理当前节点,这样可以保证从底部开始剪枝,只有当一个节点的所有子树都不包含值为 1 的节点时,这个节点才会被剪掉。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在递归函数中,如果一个节点的左右子树已被剪枝,节点本身值为0时才会返回None,这种处理方式是否会遗漏一些应被剪枝的情况?
这种处理方式不会遗漏任何应被剪枝的情况。这是因为按照题目的要求,只有当节点的值为0且其左右子树都不存在或者也是值为0且被剪枝的时候,这个节点才应当被剪枝。递归函数先处理子节点确保了在决定是否剪掉当前节点前,其子树已经根据同样的规则被处理。因此,如果一个节点及其所有子节点的值都为0,它们都将在递归过程中被正确地剪枝。
🦆
递归剪枝的顺序为先左后右,最后是当前节点。这种顺序对最终的剪枝结果有影响吗?如果先处理当前节点再递归子树会怎样?
递归剪枝的顺序(先左后右,然后当前节点)对最终结果并没有影响,因为剪枝的决定基于节点值及其子节点的状态,这需要子节点先被处理。如果先处理当前节点再递归子树,将无法正确实现剪枝逻辑。因为剪枝决定依赖于子节点的状态,如果未先递归处理子节点,就无法知道子节点是否应该被剪枝,从而不能决定当前节点是否应剪枝。因此,正确的处理顺序是关键。
🦆
递归处理时,是否有可能因为过深的递归层次导致栈溢出?这种情况下有没有非递归的替代方案?
是的,递归处理可能因为递归层次过深导致栈溢出,尤其是在处理非常深或不平衡的树时。一个非递归的替代方案是使用迭代方法结合栈或队列。例如,可以使用后序遍历的迭代版本来模拟递归的行为,先处理子节点然后处理父节点,使用栈来显式管理节点而不是依赖调用栈。这种方法需要更多的程序控制逻辑,但可以避免栈溢出的风险。

相关问题