「这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战」。
来做一道经典算法题,翻转二叉树(invert a binary tree),据说因为这道题,谷歌在面试中干掉了 homebrew 创始者 Max Howell。
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
翻转二叉树
真题描述:给你一棵二叉树的根节点
root,翻转这棵二叉树,并返回其根节点。
递归(dfs 遍历)
图解:
- 递归遍历整棵树,交换左右叶子节点的位置
- 终止条件:当前节点为
null时返回
代码实现如下:
const invertTree = function(root) {
if (root === null) {
return null;
}
const left = invertTree(root.left);
const right = invertTree(root.right);
root.left = right;
root.right = left;
return root;
};
时间复杂度:O(n),n 为二叉树节点的数目,因为我们会遍历整个二叉树。
空间复杂度:O(n),n 为递归调用栈的深度,也是当前节点在二叉树中的高度,最好为 O(logn),最坏为 O(n)。
在 JS 中,可以不用声明临时变量,使用数组结构赋值完成元素的交换,
const invertTree = function (root) {
if (root === null) {
return null
}
[root.left, root.right] = [invertTree(root.right), invertTree(root.left)]
return root
}
这么写代码就要简洁很多。
bfs
既然是遍历整棵树,当然也可以用 bfs 的思路来解决,
定义一个队列,将根节点放入到队列中,然后不断的迭代队列中的元素。
对当前元素调换其左右子树的位置,然后:
- 判断其左子树是否为空,不为空就放入队列中
- 判断其右子树是否为空,不为空就放入队列中
const invertTree = function (root) {
if (root == null) return null
const queue = []
queue.unshift(root)
while (queue.length) {
const node = queue.shift()
if (node.left) {
queue.push(node.left)
}
if (node.right) {
queue.push(node.right)
}
[node.left, node.right] = [node.right, node.left]
}
return root
}
小结
其实这道题考的是二叉树的遍历,一想到遍历,就能想到 dfs 和 bfs,再套公式一样地完成题解就行了,关于 dfs 和 bfs,更多可了解我的这两篇文章:广度优先搜索 深度优先搜索
往期