0572. 另一棵树的子树【简单】
1. 📝 题目描述
给你两棵二叉树 root 和 subRoot。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例 1:

txt
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true1
2
2
示例 2:

txt
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false1
2
2
提示:
root树上的节点数量范围是[1, 2000]subRoot树上的节点数量范围是[1, 1000]-10^4 <= root.val <= 10^4-10^4 <= subRoot.val <= 10^4
2. 🎯 s.1 - 递归
js
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} subRoot
* @return {boolean}
*/
var isSubtree = function (root, subRoot) {
// 空树不被认为是任何树的子树(根据题目要求)
if (!root) return false
return (
// 判断以当前节点为根的子树是否与subRoot相同
isSameTree(root, subRoot) ||
// 递归检查左子树和右子树
isSubtree(root.left, subRoot) ||
isSubtree(root.right, subRoot)
)
}
// 辅助函数:判断两棵树是否完全相同
function isSameTree(p, q) {
// 两个都为空,则相同
if (!p && !q) return true
// 一个为空一个不为空,则不相同
if (!p || !q) return false
// 值不相同,则不相同
if (p.val !== q.val) return false
// 递归检查左右子树
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- 时间复杂度:
,其中 是 root 树的节点数, 是 subRoot 树的节点数。最坏情况下,对 root 中的每个节点都需要与 subRoot 进行一次完全比较 - 空间复杂度:
,其中 和 分别是两棵树的高度,主要是递归调用栈的空间消耗 - 算法思路:
- 判断两棵树是否相同:编写辅助函数判断两个二叉树是否完全相同
- 遍历主树寻找匹配:遍历主树的每个节点,判断以该节点为根的子树是否与目标子树相同
3. 🎯 s.2 - 字符串匹配
js
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} subRoot
* @return {boolean}
*/
var isSubtree = function (root, subRoot) {
// 将树序列化为字符串,然后检查是否包含子串
function serialize(node) {
if (!node) return 'null'
return (
'#' + node.val + ' ' + serialize(node.left) + ' ' + serialize(node.right)
)
}
const rootStr = serialize(root)
const subRootStr = serialize(subRoot)
return rootStr.includes(subRootStr)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- 时间复杂度:
,其中 和 分别是两棵树的节点数,最坏情况下需要对主树每个节点与子树进行完全比较 - 空间复杂度:
,需要存储两棵树序列化后的字符串,空间复杂度为两树节点数之和 - 算法思路:
- 通过序列化树为字符串再进行匹配,代码简洁但会造成额外的空间开销。