剑指offer-26

剑指 Offer 26. 树的子结构

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

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

例如:
给定的树 A:

1
2
3
4
5
    3
/ \
4 5
/ \
1 2

给定的树 B:

1
2
3
  4 
/
1

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

示例

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

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

大佬题解

若树 B 是树 A 的子结构,则子结构的根节点可能为树 A 的任意一个节点。因此,判断树 B 是否是树 A 的子结构,需完成以下两步工作:

  1. 先序遍历树$A$中的每个节点$n_A$;(对应函数isSubStructure(A,B)
  2. 判断树 $A$中以$n_A$为根节点的子树 是否包含树$B$。(对应函数recur(A,B)

算法流程:

名词规定:树 A 的根节点记作 节点 A树 B 的根节点称为 节点B

recur(A, B) 函数:

1、终止条件:

  1. 当节点 $B$ 为空:说明树 $B$ 已匹配完成(越过叶子节点),因此返回 $true$;
  2. 当节点 $A$ 为空:说明已经越过树 $A$叶子节点,既匹配失败,返回$false$;
  3. 当节点 $A$ 和 $B$ 的值不同:说明匹配失败,返回$false$;

2、返回值:

  1. 判断 $A$ 和 $B$ 的左子节点是否相等,既recur(A.left,B.left);
  2. 判断 $A$ 和 $B$ 的右子节点是否相等,既recur(A.right,B.right);

isSubStructure(A, B)函数

  1. 特别处理: 当树 A 或树 B 为空时,直接返回 false;
  2. 返回值:当树 B 是树 A的子结构,则必满足以下三种情况之一,因此用或 ||连接;
    1. 以节点 A 为根节点的子树包含树B,对应 recur(A,B)
    2. 树 B 是树 A 左子树的子结构,对应 isSubStructure(A.left, B)
    3. 树 B 是树 A 右子树的子结构,对应isSubStructure(A.right, B)

以上 2. 3. 实质上是在对树 AA先序遍历

1
2
3
4
5
6
7
8
9
10
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
def recur(A, B):
if not B: return True
if not A or A.val != B.val: return False
return recur(A.left, B.left) and recur(A.right, B.right)

return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))


作者

bd160jbgm

发布于

2021-06-10

更新于

2021-06-10

许可协议