leetcode
leetcode 1501 ~ 1550
改变二叉树的根节点

改变二叉树的根节点

难度:

标签:

题目描述

代码结果

运行时间: 31 ms, 内存: 16.4 MB


/*
 * 题目思路:
 * 1. 虽然Java Stream不适合直接处理树结构,但我们可以借鉴其思想,
 *    使用递归来遍历和调整树的结构。
 * 2. 从当前的根节点向下遍历到指定的新根节点。
 * 3. 沿途将每个节点的父指针断开,并指向其父节点。
 */
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    public TreeNode flipBinaryTree(TreeNode root, TreeNode leaf) {
        return flip(root, null, leaf);
    }

    private TreeNode flip(TreeNode root, TreeNode parent, TreeNode leaf) {
        if (root == null) return null;
        if (root == leaf) {
            root.left = parent;
            return root;
        }

        TreeNode newRoot = flip(root.left, root, leaf);
        root.left = parent;
        return newRoot;
    }
}

解释

方法:

此题解的主要思路在于将二叉树中从给定的叶节点开始到根节点的路径上的所有节点进行翻转。具体步骤如下:首先遍历从叶节点到根节点的路径,将这些节点存储在数组中。然后从叶节点开始,逐个将每个节点的父节点变为它的子节点,同时清除原有的父子关系,并调整兄弟节点的关系。这样,最初的叶节点变成了新的根节点,原来的根节点变成了新根的一个子节点,整个树的结构被反转了。

时间复杂度:

O(h)

空间复杂度:

O(h)

代码细节讲解

🦆
如何确保给定的叶节点`leaf`确实是一个叶节点,而不是树中的其他节点?
为了确保提供的节点`leaf`是一个叶节点,我们可以在代码中添加一个检查步骤来验证此条件。具体来说,可以在`flipBinaryTree`函数的开始处添加如下的检查:`if leaf.left is not None or leaf.right is not None: raise ValueError('提供的节点不是叶节点')`。这种检查可以确保节点没有子节点,从而符合叶节点的定义。
🦆
在将原父节点变为当前节点的子节点时,如果当前节点已有左子节点,为什么选择将原父节点放在左边而把原左子节点移至右侧?
在这个题解中,选择将原父节点放置在当前节点的左侧,主要是为了保持一致的转换规则,即始终将原父节点变为新的左子节点。这样做简化了逻辑,减少了条件判断。将原有的左子节点移至右侧,是为了确保不丢失任何子树。这种方法确保了树的结构在翻转过程中仍然被保持完整。
🦆
在修改节点的父子关系后,如何处理可能因此操作造成的树的不平衡问题?
在这个特定的问题中,树的平衡性不是首要考虑的问题,因为目的是要反转路径,而不是维持树的平衡。然而,在实际的应用中,如果需要维护树的平衡,可能需要在翻转操作后使用树的平衡技术如AVL树或红黑树的旋转操作来重新平衡树。在当前的算法实现中,并未包含处理不平衡的逻辑。
🦆
请问在代码中如何处理根节点自身没有父节点的情况,即如何判断并结束整个反转操作的循环?
在代码中,根节点的特殊情况通过循环条件`while p != root:`来处理。这个循环会一直执行,直到变量`p`(表示当前正在处理的节点)达到根节点。一旦到达根节点,循环自然结束,因为根节点的父节点是`None`,这也是为什么在循环之后还需要将`root`添加到路径数组`arr`中的原因。这样确保了即使根节点没有父节点,整个翻转操作也能正确完成。

相关问题