[路飞]_老白的算法学习笔记05(翻转二叉树)

311 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

翻转二叉树

早上好。在前面我们学习常用的排序算法中的堆排序(heapSort)用到了二叉树(Binary tree),今天我们来分析一道简单的二叉树问题。这道二叉树题虽说简单却也非常有来历,据说 Mac上著名软件 Homebrew的作者 Max Howell就是因为不会在白板上写出翻转二叉树算法而被谷歌拒之门外。

emoji.png

谷歌:我们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:

invert1-tree.jpg

Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]

好了,这个就是大概的题目,大家可以用5分钟的时间想一想要怎么去实现。要做原题的可以直接滑到文末有 leetcode的引用链接。

解题思路

当我看到这个翻转题目,直觉告诉我使用递归。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

这里的难点就是对递归函数的理解,递归是分治思想的具体实现方法,在计算机中使用调用栈来实现递归内容的保存,把整体问题分成一个一个调用栈,然后在调用栈的尾部(递归终止条件)进行求解(治理),从而一步一步向上求出整体的结果。

动图演示

0f91f7cbf5740de86e881eb7427c6c3993f4eca3624ca275d71e21c5e3e2c550-226_2.gif

代码实现


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;
};

迭代方法实现本题

理论上递归和迭代可以互相转换。那么读者朋友们能不能用迭代的方式来解决本题呢? 这就作为今天的思考题吧。欢迎读者朋友留言反馈。

引用

226. 翻转二叉树