vlambda博客
学习文章列表

难倒Homebrew发明人的翻转二叉树到底有多简单?


什么是翻转二叉树

大家都知道Homebrew发明人Max Howell面试谷歌时,被一道翻转二叉树的题目给难倒了。那么什么是翻转二叉树呢?看看下图就明白了。



简单地说,就是对于一棵二叉树及其所有子树,交换其左右位置。

思路

首先,看到一棵二叉树时,我们不要被庞大的分支结构所吓倒,其实,其基本构成就是根节点左子树右子树这三个元素而已。大多数问题只需要考虑这三者之间的关系就能被解决;
其次,对于树相关的问题,我们的第一反应是尝试能否通过递归的方法来实现。

理清了二叉树的基本结构(根节点左子树右子树),并使用递归的思路来思考,自然可以得出下面的递归过程:

  • 让左子树完成翻转

  • 让右子树完成翻转

  • 交换左右子树

自然就能完成全部的翻转过程了。可以参考下图:


我们先完成了左子树的翻转,接着完成了右子树的翻转,最后在根节点处交换了左右子树。可以很自然地写出如下的递归代码:


class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left, root.right = right, left
return root

考虑递归终止条件后的最终代码

递归相关的代码,最重要的有两点,一是理清递归的思路,也就是上文所述的内容,另一点是递归的终止条件。从上述递归过程可以知道,当根节点为空或者递归到叶子节点时,由于左右子树均为空,那么直接返回就行了。所以为完备性考虑,修正递归代码为:

class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return root

left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left, root.right = right, left
return root

回顾

树相关的操作,先考虑递归能否实现,所谓的递归过程,也无非是考虑根节点左子树右子树三者之间的关系。最后再考虑一下根节点为空叶子节点的边界情况,那么基本能写个七七八八出来了。好了,这样就可以胜过Max Howell了。狗头滚粗...