Article / 文章

LeetCode 156 上下翻转二叉树:递归巧妙改变树结构

给定一个二叉树,其中所有的右节点要么是具有兄弟节点(拥有相同父节点的左节点)的叶子节点,要么为空,将此二叉树上下翻转并将它变成一棵树,原来的右节点将转换成左叶子节点。返回新的根。

题目描述

给定一个二叉树,其中所有的右节点要么是具有兄弟节点(拥有相同父节点的左节点)的叶子节点,要么为空,将此二叉树上下翻转并将它变成一棵树,原来的右节点将转换成左叶子节点。返回新的根。

难度

中等

题目链接

点击在LeetCode中查看题目

示例

示例 1:

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

示例 2:

输入: root = []
输出: []

示例 3:

输入: root = [1]
输出: [1]

提示

  • 树中节点数在范围 [0, 10]
  • 1 <= Node.val <= 10
  • 树中的每个右节点都有一个对应的兄弟节点
  • 树中的每个右节点都是叶子节点

解题思路

方法:递归

使用递归方法翻转二叉树。 关键点:

  1. 如果根节点为空或没有左子节点,直接返回根节点
  2. 递归处理左子树
  3. 将当前节点的左子节点设为新的根节点
  4. 将当前节点的右子节点设为左子节点的左子节点
  5. 将当前节点设为左子节点的右子节点
  6. 将当前节点的左右子节点设为空

时间复杂度:O(n),其中n是树中节点个数。 空间复杂度:O(h),其中h是树的高度。

代码实现

C# 实现

public class Solution {
    public TreeNode UpsideDownBinaryTree(TreeNode root) {
        if (root == null || root.left == null) {
            return root;
        }
        
        TreeNode newRoot = UpsideDownBinaryTree(root.left);
        
        root.left.left = root.right;
        root.left.right = root;
        root.left = null;
        root.right = null;
        
        return newRoot;
    }
}

Python 实现

class Solution:
    def upsideDownBinaryTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root or not root.left:
            return root
            
        new_root = self.upsideDownBinaryTree(root.left)
        
        root.left.left = root.right
        root.left.right = root
        root.left = None
        root.right = None
        
        return new_root

C++ 实现

class Solution {
public:
    TreeNode* upsideDownBinaryTree(TreeNode* root) {
        if (!root || !root->left) {
            return root;
        }
        
        TreeNode* newRoot = upsideDownBinaryTree(root->left);
        
        root->left->left = root->right;
        root->left->right = root;
        root->left = nullptr;
        root->right = nullptr;
        
        return newRoot;
    }
};

性能分析

各语言实现的性能对比:

实现语言 执行用时 内存消耗 特点
C# 92 ms 38.2 MB 实现简洁,性能适中
Python 156 ms 16.8 MB 代码最简洁
C++ 24 ms 9.6 MB 性能最优

补充说明

代码亮点

  1. 使用递归方法,代码简洁清晰
  2. 处理了各种边界情况
  3. 空间复杂度为O(h),其中h是树的高度

常见错误

  1. 没有处理空树的情况
  2. 没有处理只有一个节点的情况
  3. 指针引用处理不当

相关题目

讨论

有几个问题可以思考一下:

  1. 这道题的翻转规则比较特殊,能用画图的方式理解一下翻转前后的变化吗?
  2. 递归和迭代两种方法,哪个更容易理解?
  3. 这道题在实际开发中有什么应用场景?

欢迎在评论区讨论。


如果你都看到这里了,说明还是有点收获的吧?给个赞鼓励一下呗。