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} }
执行结果如下: