2021-06-13:如果一个节点X,它左树结构和右树结构完全一样,那么我们说以X为头的树是相等树。给定一棵二叉树的头节点head,返回head整棵树上有多少棵相等子树。

福大大 答案2021-06-14:

方法一:自然智慧。
递归函数:头num=左num+右num+0或1。
相等判断函数:左结构=右结构,O(N)。
树越不平衡,复杂度越低,因此算复杂度的时候,只需要考虑平衡树。
master公式:T(N)=2T(N/2)+O(N)。2T(N/2)是递归。O(N)是相等判断函数。
根据master公式,时间复杂度是O(N*logN)。

方法二:方法一的相等判断函数用哈希函数。
递归函数:头num=左num+右num+0或1。头哈希=【左哈希+头值+右哈希】的哈希值。这个递归有两个返回值。
相等判断函数:左结构=右结构,用哈希值判断,O(1)。
树越不平衡,复杂度越低,因此算复杂度的时候,只需要考虑平衡树。
master公式:T(N)=2T(N/2)+O(1)。2T(N/2)是递归。O(1)是相等判断函数。
根据master公式,时间复杂度是O(N)。

代码用golang编写。代码如下:

package main

import (
    "crypto/md5"
    "fmt"
)

func main() {
    head := &Node{Val: 1}
    head.Left = &Node{Val: 2}
    head.Right = &Node{Val: 2}
    head.Left.Left = &Node{Val: 3}
    head.Left.Right = &Node{Val: 4}
    head.Right.Left = &Node{Val: 3}
    head.Right.Right = &Node{Val: 4}
    ret1 := sameNumber1(head)
    fmt.Println(ret1)
    ret2 := sameNumber2(head)
    fmt.Println(ret2)
}

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

// 方法一:时间复杂度O(N * logN)
func sameNumber1(head *Node) int {
    if head == nil {
        return 0
    }
    return sameNumber1(head.Left) + sameNumber1(head.Right) + twoSelectOne(same(head.Left, head.Right), 1, 0)
}

func same(left *Node, right *Node) bool {
    if left == nil && right == nil {
        return true
    }
    if left == nil || right == nil {
        return false
    }
    // 两个都不为空
    return left.Val == right.Val && same(left.Left, right.Left) && same(left.Right, right.Right)
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

type Info struct {
    ans int
    str string
}

//方法二
func sameNumber2(head *Node) int {
    return process2(head).ans
}

func process2(head *Node) *Info {
    if head == nil {
        return &Info{ans: 0, str: fmt.Sprintf("%x", md5.Sum([]byte("#,")))}
    }
    l := process2(head.Left)
    r := process2(head.Right)
    ans := twoSelectOne(l.str == r.str, 1, 0) + l.ans + r.ans
    str := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d,%s%s", head.Val, l.str, r.str))))
    return &Info{ans: ans, str: str}
}

执行结果如下:
图片


左神java代码