「力扣226」翻转二叉树

206 阅读2分钟

题目

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

原题链接

翻转二叉树

思路

对于任意一个结点都是交换左右子树再返回,所以可以设计一个递归函数来实现。

设计递归

递归含义

  1. 对于每一个结点root,交换它的左子树和右子树,交换完成后返回二叉树头root
  2. 如果root为空左右子树都为空就不用交换了。

递归过程

对于任意一个结点:

  1. 先递进去左子树左子树内部交换完毕。
  2. 回到父结点,递进去右子树右子树内部交换完毕。
  3. 回到父结点,此时左右子树内部都已交换好了,交换左右子树,返回父结点爷爷结点使用。

宏观视角

🔥交换过程是: 左子树内部交换->右子树内部交换->交换左右子树,即左右头,所以是一个后序遍历的过程。

🌲从 root 开始,左子树一路到底,然后返回到父结点,再进入右子树,再返回到父结点。然后父结点交换左右子树,再返回父结点爷爷结点使用,这就是宏观的过程。

💡值得注意的是,每次返回的结点必然是以这个结点为头的整棵树已经交换完毕的了,这一点需要明白。

手绘图解

为了加深印象,笔者将自己的理解输出成一张手绘图,如下:

lc226.jpeg

代码

TypeScript

function invertTree(root: TreeNode | null): TreeNode | null {
    // 头为空,不用交换子树,直接返回 root
    if (!root) {
        return root;
    }

    // 左右子树都为空,不用交换子树,直接返回 root
    if (!root.left && !root.right) {
        return root;
    }

    // 1. 来到左子树
    // 左子树`递`进去直到叶子结点,返回叶子头,再到叶子父结点交换左右子树,返回叶子父..
    // 最后返回`整棵左子树交换完毕`的头
    const left = invertTree(root.left);

    // 2. 从左子树回到父结点

    // 3. 从父结点进入右子树
    // 左子树交换完毕,交换右子树
    const right = invertTree(root.right);

    // 4. 从右子树回到父结点
    // 左右子树各自内部的结点交换完毕,头结点的两棵子树开始交换
    root.left = right;
    root.right = left;

    // root这棵树交换完毕,返回头给root的父级使用。
    return root;
};