另一棵树的子树
- https://leetcode.cn/problems/subtree-of-another-tree/description/
描述
- 给你两棵二叉树 root 和 subRoot
- 检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树
- 如果存在,返回 true ;否则,返回 false
- 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点
- tree 也可以看做它自身的一棵子树
示例 1
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true
示例 2
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false
提示
- root 树上的节点数量范围是 [1, 2000]
- subRoot 树上的节点数量范围是 [1, 1000]
- - 1 0 4 10^4 104 <= root.val <= 1 0 4 10^4 104
- - 1 0 4 10^4 104 <= subRoot.val <= 1 0 4 10^4 104
Typescript 版算法实现
1 ) 方案1:深度优先搜索暴力匹配
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean {
if (!root) return false;
return check(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
function check(a: TreeNode | null, b: TreeNode | null): boolean {
if (!a && !b) return true;
if (!a || !b) return false;
if (a.val === b.val) return check(a.left, b.left) && check(a.right, b.right);
return false;
}
2 ) 方案2:深度优先搜索序列上做串匹配
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function getMaxElement(root: TreeNode | null, maxElement: { value: number }): void {
if (!root) return;
maxElement.value = Math.max(maxElement.value, root.val);
getMaxElement(root.left, maxElement);
getMaxElement(root.right, maxElement);
}
function getDfsOrder(root: TreeNode | null, order: number[], lNull: number, rNull: number): void {
if (!root) return;
order.push(root.val);
if (root.left) {
getDfsOrder(root.left, order, lNull, rNull);
} else {
order.push(lNull);
}
if (root.right) {
getDfsOrder(root.right, order, lNull, rNull);
} else {
order.push(rNull);
}
}
function kmp(sOrder: number[], tOrder: number[]): boolean {
const sLen = sOrder.length, tLen = tOrder.length;
const fail: number[] = new Array(tLen).fill(-1);
for (let i = 1, j = -1; i < tLen; ++i) {
while (j !== -1 && tOrder[i] !== tOrder[j + 1]) {
j = fail[j];
}
if (tOrder[i] === tOrder[j + 1]) {
++j;
}
fail[i] = j;
}
for (let i = 0, j = -1; i < sLen; ++i) {
while (j !== -1 && sOrder[i] !== tOrder[j + 1]) {
j = fail[j];
}
if (sOrder[i] === tOrder[j + 1]) {
++j;
}
if (j === tLen - 1) {
return true;
}
}
return false;
}
function isSubtree(s: TreeNode | null, t: TreeNode | null): boolean {
let maxElement = Number.MIN_SAFE_INTEGER;
getMaxElement(s, { value: maxElement });
getMaxElement(t, { value: maxElement });
const lNull = maxElement + 1;
const rNull = maxElement + 2;
const sOrder: number[] = [];
const tOrder: number[] = [];
getDfsOrder(s, sOrder, lNull, rNull);
getDfsOrder(t, tOrder, lNull, rNull);
return kmp(sOrder, tOrder);
}
3 ) 方案3:基于两棵树是否相同来判断
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isSubtree(root:TreeNode | null, subRoot:TreeNode | null) {
// 不停地比较, 某一个子树,是不是和subRoot一样
if(!root) return false
if((root.val === subRoot.val) && (isSameTree(root,subRoot))) return true
return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot)
};
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
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)
};