leetcode
leetcode 151 ~ 200
上下翻转二叉树

上下翻转二叉树

难度:

标签:

题目描述

代码结果

运行时间: 20 ms, 内存: 16.7 MB


// 题目思路:使用递归并结合Java Stream API进行翻转。此题目不太适合使用纯Stream API实现,但可以结合递归实现。
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
import java.util.stream.Stream;
 
public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        // 使用Stream API交换左右子节点
        Stream.of(root.left, root.right).reduce((left, right) -> {
            root.left = right;
            root.right = left;
            return null;
        });
        // 递归地翻转左子树和右子树
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

解释

方法:

这个题解采用了迭代的方式来翻转二叉树。通过将每个节点的左右子树进行交换,并同时记录该节点的父节点和原右子树,就可以实现二叉树的上下翻转。具体来说,使用 parent 变量记录当前节点的父节点,right 变量暂存当前节点的右子树,然后将当前节点的左子树赋给 root.left,右子树赋为 parent,最后更新 parent 为当前节点,并将 root 指向原左子节点,进入下一次迭代。当 root 为空时,新的树根就是 parent。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
迭代方法中,为什么选择在遍历时仅通过左子节点向下进行,而不是同时考虑右子节点?
在上下翻转二叉树的过程中,我们的目标是将原始的树结构中的每一层节点从左到右的连接关系转变为从上到下的连接关系。这意味着原来的左子节点将成为新的根节点,而原来的根节点将转变为新的右子节点。因此,我们需要从左子节点开始迭代,逐步向下进行,使每个节点的左子节点成为新的根节点。如果同时考虑右子节点,会导致迭代逻辑复杂化,并且与翻转的目标结构不符,因此选择仅通过左子节点向下进行。
🦆
在迭代过程中,如何确保不会丢失对原始二叉树的右子树的引用,特别是在多次迭代中?
在迭代过程中,我们通过使用一个额外的变量 `right` 来暂存当前节点的右子树。每次迭代时,我们首先将 `right` 变量设置为当前节点的右子节点,然后在处理下一个节点之前,我们不再改变 `right` 的值。这样,每个节点的右子树都被安全地保存在 `right` 变量中,直到这个节点被处理完毕,确保了在整个迭代过程中不会丢失对任何右子树的引用。
🦆
题解中提到的 `parent` 和 `right` 变量在算法中分别起到了什么作用?请解释它们在翻转过程中的具体用途。
`parent` 变量在算法中用于保存当前节点的父节点,这是因为在翻转过程中原来的父节点将变成新的右子节点。因此,我们需要一个变量来记录这个信息,以便于将当前节点的右子树指针指向其原父节点。`right` 变量则用于暂存当前节点的原右子树。在迭代过程中,当前节点的左子树会被赋给 `root.left`,而原右子树存储在 `right` 中,将在下次迭代中被重新赋值给新的节点的左子树,从而保持树结构的正确性。
🦆
你如何处理原始树根节点的左右子树,在树完全翻转后它们的指向关系是如何的?
在树的翻转过程结束时,原始树根节点将变成新树的最右下的叶节点。原始树根的左子树将转变为其右子节点,而其右子树将转变为其左子树。这种变化是通过迭代过程中连续更新节点的左右指针来完成的。最终,树的最初始根节点的左右子树将被交换,使其符合翻转后的新结构。

相关问题

反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

 

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

 

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

 

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?