226. 翻转二叉树

题目描述

image

解题思路

二叉树的题一般都有对应的模板,我们做题时可以参考对应模板
二叉树解题的思维模式分两类:

  • 1、是否可以通过遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现,这叫「遍历」的思维模式。

  • 2、是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案?如果可以,写出这个递归函数的定义,并充分利用这个函数的返回值,这叫「分解问题」的思维模式。

无论使用哪种思维模式,你都需要思考:

如果单独抽出一个二叉树节点,它需要做什么事情?需要在什么时候(前/中/后序位置)做?其他的节点不用你操心,递归函数会帮你在所有节点上执行相同的操作。

解题步骤

1、这题能不能用「遍历」的思维模式解决?

可以,我写一个 traverse 函数遍历每个节点,让每个节点的左右子节点颠倒过来就行了。

单独抽出一个节点,需要让它做什么?让它把自己的左右子节点交换一下。

需要在什么时候做?好像前中后序位置都可以。

综上,可以写出如下解法代码

// 主函数
TreeNode invertTree(TreeNode root) {
    // 遍历二叉树,交换每个节点的子节点
    traverse(root);
    return root;
}

// 二叉树遍历函数
void traverse(TreeNode root) {
    if (root == null) {
        return;
    }

    /**** 前序位置 ****/
    // 每一个节点需要做的事就是交换它的左右子节点
    TreeNode tmp = root.left;
    root.left = root.right;
    root.right = tmp;

    // 遍历框架,去遍历左右子树的节点
    traverse(root.left);
    traverse(root.right);
}

你把前序位置的代码移到后序位置也可以,但是直接移到中序位置是不行的,需要稍作修改,这应该很容易看出来吧,我就不说了。

按理说,这道题已经解决了,不过为了对比,我们再继续思考下去。

2、这题能不能用「分解问题」的思维模式解决?

然后思考,对于某一个二叉树节点 x 执行 invertTree(x),你能利用这个递归函数的定义做点啥?

我可以用 invertTree(x.left) 先把 x 的左子树翻转,再用 invertTree(x.right) 把 x 的右子树翻转,最后把 x 的左右子树交换,这恰好完成了以 x 为根的整棵二叉树的翻转,即完成了 invertTree(x) 的定义。

直接写出解法代码:

var invertTree = function(root) {
    const reverse= function(root) {
        if(!root) return root
        let temp = root.left
        root.left = reverse(root.right)
        root.right = reverse(temp)
        return root
    }
    let res = reverse(root)
    return res
};

参考链接

posted @ 2022-10-15 15:22  含若飞  阅读(14)  评论(0编辑  收藏  举报