我们先从简单的题开始,看看力扣第 226 题「 翻转二叉树 」,输入一个二叉树根节点 root
,让你把整棵树镜像翻转,比如输入的二叉树如下:
4
/ \
2 7
/ \ / \
1 3 6 9
算法原地翻转二叉树,使得以 root
为根的树变成:
4
/ \
7 2
/ \ / \
9 6 3 1
思考前面的提纲: 二叉树思想提纲
1、这题能不能用「遍历」的思维模式解决?
可以,我写一个 traverse
函数遍历每个节点,让每个节点的左右子节点颠倒过来就行了。
单独抽出一个节点,需要让它做什么?让它把自己的左右子节点交换一下。
需要在什么时候做?好像前中后序位置都可以。
作者可视化面板: 东哥带你刷二叉树(思路篇) | labuladong 的算法笔记
你把前序位置的代码移到后序位置也可以,但是直接移到中序位置是不行的[因为交换左右子节点,不交换根节点] ,需要稍作修改,这应该很容易看出来吧,我就不说了。
按理说,这道题已经解决了,不过为了对比,我们再继续思考下去。
2、这题能不能用「分解问题」的思维模式解决?
我们尝试给 invertTree
函数赋予一个定义:
然后思考,对于某一个二叉树节点 x
执行 invertTree(x)
,你能利用这个递归函数的定义做点啥?
我可以用 invertTree(x.left)
先把 x
的左子树翻转,再用 invertTree(x.right)
把 x
的右子树翻转,最后把 x
的左右子树交换,这恰好完成了以 x
为根的整棵二叉树的翻转,即完成了 invertTree(x)
的定义。
直接写出解法代码:
看看作者可视化辅以理解:
东哥带你刷二叉树(思路篇) | labuladong 的算法笔记
这种「分解问题」的思路,核心在于你要给递归函数一个合适的定义,然后用函数的定义来解释你的代码;如果你的逻辑成功自恰,那么说明你这个算法是正确的。
好了,这道题就分析到这,「遍历」和「分解问题」的思路都可以解决,看下一道题。
暂时理解不太深刻,再多回头看看吧