[LeetCode By Go 20]226. Invert Binary Tree

HomeBrew作者去Google面试做错的一道题,影响很大,大家一定要研究下这道题。

《[LeetCode By Go 20]226. Invert Binary Tree》

事件回放

2015 年 6 月 10 日,Homebrew 的作者 @Max Howell 在 twitter 上发表了如下一内容:

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.

事情大概是说,Max Howell 去 Google 面试,

面试官说:虽然在 Google 有 90% 的工程师用你写的 Homebrew,但是你居然不能在白板上写出翻转二叉树的代码,所以滚蛋吧。

这件事情如果发生在任何一个应届生身上,那是再正常不过的了,但是偏偏面试者是有名的 Max Howell。于是乎,关于应该如何面试程序员,再一次被大家热烈的讨论。知乎上也有相关的讨论,如何看待 Max Howell 被 Google 拒绝?
大家也可以看一下 QuoraHacker News 上的讨论。

题目

Invert a binary tree.

     4
   /   \
  2     7
 / \   / \
1   3 6   9

to

     4
   /   \
  7     2
 / \   / \
9   6 3   1

解题思路

翻转一个二叉树,直观上看,就是把二叉树的每一层左右顺序倒过来。比如问题中的例子,第三层1-3-6-9经过变换后变成了9-6-3-1,顺序反过来就对了。 再仔细观察一下,对于上面的例子,根节点(root)的左子节点及其所有的子孙节点构成根节点的左子树(left subtree),同样的,根节点(root)的右子节点及其所有的子孙节点构成根节点的右子树(right subtree)。因此翻转一个二叉树,就是把根节点的左子树翻转一下,同样的把右子树翻转一下,在交换左右子树就可以了。
《[LeetCode By Go 20]226. Invert Binary Tree》 左子树和右子树

当然,翻转左子树和右子树的过程和当前翻转二叉树的过程没有区别,就是递归的调用当前的函数就可以了。 因此,翻转二叉树的步骤可总结如下:

  1. 翻转根节点的左子树(递归调用当前函数)
  2. 翻转根节点的右子树(递归调用当前函数)
  3. 交换根节点的左子节点与右子节点

代码

invertBinaryTree.go

package _226_Invert_Binary_Tree

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func InvertTree(root *TreeNode) *TreeNode {
    if nil == root {
        return nil
    }

    if nil != root.Left {
        InvertTree(root.Left)
    }

    if nil != root.Right {
        InvertTree(root.Right)
    }

    root.Left, root.Right = root.Right, root.Left

    return root
}

测试代码

invertBinaryTree_test.go

package _226_Invert_Binary_Tree

import (
    "testing"
    "fmt"
)

func InitNode(val int, left *TreeNode, right *TreeNode) (ret *TreeNode){
    ret = new(TreeNode)
    ret.Val = val
    ret.Left = left
    ret.Right = right

    return ret
}


func treeEqual(t1 *TreeNode, t2 *TreeNode) bool{
    if t1.Val != t2.Val {
        return false
    }

    if nil == t1.Left && nil != t2.Left {
        return false
    }else if nil != t1.Left && nil == t2.Left {
        return false
    } else if nil != t1.Left && nil != t2.Left {
        left := treeEqual(t1.Left, t2.Left)
        if !left {
            return false
        }
    }

    if nil == t1.Right && nil != t2.Right {
        return false
    }else if nil != t1.Right && nil == t2.Right {
        return false
    }else if nil != t1.Right && nil != t2.Right {
        right := treeEqual(t1.Right, t2.Right)
        if !right {
            return false
        }
    }

    return true
}

func TreePrint(t1 *TreeNode) {

    if nil == t1 {
        fmt.Printf("null, ")
        return
    } else {
        fmt.Printf("%+v, ", t1.Val)
    }

    TreePrint(t1.Left)
    TreePrint(t1.Right)
}

func TestInvertTree(t *testing.T) {
    l3_1 := InitNode(1, nil, nil)
    l3_2 := InitNode(3, nil, nil)
    l3_3 := InitNode(6, nil, nil)
    l3_4 := InitNode(9, nil, nil)

    l2_1 := InitNode(2, l3_1, l3_2)
    l2_2 := InitNode(7, l3_3, l3_4)

    input := InitNode(4, l2_1, l2_2)



    w2_1 := InitNode(7, l3_4, l3_3)
    w2_2 := InitNode(2, l3_2, l3_1)

    want := InitNode(4, w2_1, w2_2)

    ret := InvertTree(input)

    equal := treeEqual(want, ret)

    TreePrint(want)
    fmt.Println()
    TreePrint(ret)
    fmt.Println()

    if equal {
        t.Logf("pass")
    } else {
        t.Errorf("fail, want %+v, get %+v", want, ret)
    }
}
    原文作者:miltonsun
    原文地址: https://www.jianshu.com/p/4883447d62f2
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞