汇总:剑指offer算法合集
题目
输入两棵二叉树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]
输出:false
示例 2:
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
限制:
0 <= 节点个数 <= 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof
解题思路
- 如果B是A的子树,那么B的根节点一定是A的某个节点,我们首先需要找到这个节点,可以遍历A去找出这个节点
- A找到某个节点和子B的根节点相等,那么A以节点下的子树可能就是B子树,因此我们开始遍历A的这个节点的左右子树,看它是否结构和值都等于B的左右,如果遍历过程中发现以下情况,说明没找到,返回false:
- 遍历发现A的左右子树的中某个节点为空了,但B左右子树对应的位置节点却不为空
- 遍历发现A的左右子树的某个节点和B子树同位置的节点不相等
- 如果一直遍历到B的左右子树的节点为空,说明B已经全部遍历过,也就是A存在结构和值都和B一样的子树,因此B是A的子树,则返回true
- 如果上面返回了false,说明A这个根节点下的子树和B子树并不一样,就继续寻找下一个和B根节点相同的节点
复杂度分析
递归嵌套,假设A节点数为m,B节点数为n,那么时间复杂度为O(mn)
,用到递归栈,最深时是A是一条链表的形式,空间复杂度为O(m)
代码实现
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
//A或B为空,说明已经在这个子树上遍历到最后了,都没找到,就返回false
if (A == null || B == null) return false;
//检查以A当前节点作为根节点,是否能和B子树对应上
return isSub(A, B)
//如果不是,则遍历A当前节点的左子树
|| isSubStructure(A.left, B)
//如果A当前节点的左子树也没找到,就遍历右子树
|| isSubStructure(A.right, B);
}
public boolean isSub(TreeNode A, TreeNode B){
//如果B已经遍历完了,说明全部对应上了,B就是A当前节点作为根节点的子树
if (B == null) return true;
//如果B没遍历完但A的当前子树遍历完了,说明不等
if (A == null) return false;
//如果A当前节点和B当前节点相等,则继续遍历A和B当前节点的左子树和右子树
return A.val == B.val && isSub(A.left, B.left) && isSub(A.right, B.right);
}
}