「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
翻转二叉树
早上好。在前面我们学习常用的排序算法中的堆排序(heapSort)用到了二叉树(Binary tree),今天我们来分析一道简单的二叉树问题。这道二叉树题虽说简单却也非常有来历,据说 Mac上著名软件 Homebrew的作者 Max Howell就是因为不会在白板上写出翻转二叉树算法而被谷歌拒之门外。
谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。
那么接下来就让我们看一看这道让 Max Howell和google失之交臂的算法题。
题目描述
翻转一棵二叉树。(Given the root of a binary tree, invert the tree, and return its root.)
示例1:
输入:
4
/ \
2 7
/ \ / \
1 3 6 9
输出:
4
/ \
7 2
/ \ / \
9 6 3 1
示例2:
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]
好了,这个就是大概的题目,大家可以用5分钟的时间想一想要怎么去实现。要做原题的可以直接滑到文末有 leetcode的引用链接。
解题思路
当我看到这个翻转题目,直觉告诉我使用递归。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。
这里的难点就是对递归函数的理解,递归是分治思想的具体实现方法,在计算机中使用调用栈来实现递归内容的保存,把整体问题分成一个一个调用栈,然后在调用栈的尾部(递归终止条件)进行求解(治理),从而一步一步向上求出整体的结果。
动图演示
代码实现
var invertTree = function(root) {
// 判断若 节点为空, 或者为叶子结点的情况 直接返回该节点
if(!root || !root.left && !root.right) return root;
// 递归实现左右子节点的翻转,此时你可认为执行完下面的代码左右子节点都已经翻转完毕,就是我们想要的结构
invertTree(root.left);
invertTree(root.right);
// 子节点的子节点已经交换完毕,接下来只要交换本root节点的左右子节点即可,典型的swap交换
let temp = root.left;
root.left = root.right;
root.right = temp;
return root;
};
迭代方法实现本题
理论上递归和迭代可以互相转换。那么读者朋友们能不能用迭代的方式来解决本题呢? 这就作为今天的思考题吧。欢迎读者朋友留言反馈。