题目描述

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:

     3
    / \    
   4   5
  / \
 1   2

给定的树 B:

  4 
 /
1

返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例1

输入:A = [1,2,3], B = [3,1]		//	AB为深度优先表示的完全二叉树
输出:false

示例2

输入:A = [3,4,5,1,2], B = [4,1]
输出:true

算法分析

  • 要确定B树是否为A树的子结构,要先确定B的根节点是否被包含在A树内,因此可以考虑用广度优先搜索遍历A树的每一个节点,判断当前节点curNode的值是否等于B树的根节点,若值相等,则用isAContainsB()函数判断以curNode为根节点的树是否包含B树; 若值不相等,则直接跳过,继续遍历A树的节点。
  • isAContainsB()函数用递归实现,需要注意对AB判空。
  • 设A的节点数为m,B的节点数为n,则总的时间复杂度为遍历A树的时间乘上isAContainsB()函数花费的时间,即O( m ∗ n m*n m∗n)。
  • 因为在BFS的过程中用到了nodes数组保存树的节点,所以空间复杂度为O( n n n)。

Golang代码如下

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isAContainsB(A *TreeNode, B *TreeNode) bool {
	if B == nil {
		return true
	}
    if A == nil {
        return false
    }
	if A.Val == B.Val {
		return isAContainsB(A.Left, B.Left) && isAContainsB(A.Right, B.Right)
	}
	return false
}

func isSubStructure(A *TreeNode, B *TreeNode) bool {
	if A == nil || B == nil {
		return false
	}
	nodes := []*TreeNode{A}
	for len(nodes) > 0 {
		curNode := nodes[0]
		if curNode.Val == B.Val {
			if isAContainsB(curNode, B) {
				return true
			}
		}
		nodes = nodes[1:]
		if curNode.Left != nil {
			nodes = append(nodes, curNode.Left)
		}
		if curNode.Right != nil {
			nodes = append(nodes, curNode.Right)
		}
	}
	return false
}