# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def recur(self,A,B):
if not B: return True
if not A or A.val !=B.val: return False
return self.recur(A.left,B.left) and self.recur(A.right,B.right) #如果A,B的值都相等,那么继续比较子结构是否相等
def isSubStructure(self, A: Optional[TreeNode], B: Optional[TreeNode]) -> bool:
if A and not B: return False
if not A and B: return False
if not A and not B: return False
return (A and B) and (self.recur(A,B) or self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B)) # A,B同时都存在,要么A,B匹配上,要么B与A的子结构匹配。两个递归
class Solution:
def isSubTree(self, A, B):
if not B: return True
if not A: return False
if A.val != B.val: return False
return self.isSubTree(A.left, B.left) and self.isSubTree(A.right, B.right)
def isSubStructure(self, A: Optional[TreeNode], B: Optional[TreeNode]) -> bool:
if not A or not B: return False
if self.isSubTree(A, B):
return True
if self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B):
return True
return False
/**
方法一:递归
B逐个与A的每个节点进行check是否有相同结构,时间复杂度O(n**2)
*/
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
boolean res = false;
if (A != null && B != null){
res = check(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
return res;
}
public boolean check(TreeNode a, TreeNode b){
if (b == null){
return true;
}
if (a == null){
return false;
}
if (a.val != b.val){
return false;
}
return check(a.left, b.left) && check(a.right, b.right);
}
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if (A == null || B == null) {
return false;
}
return recur(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
public static boolean recur(TreeNode A, TreeNode B) {
if (B == null) return true;
if (A == null || A.val != B.val) return false;
return recur(A.left, B.left) && recur(A.right, B.right);
}
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A null || B null) return false;
return dfs(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
// 如果任一树为空,则直接返回false
if (A null || B null) {
return false;
}
// 检查从当前节点A开始是否包含与B相同的子树结构,或者递归检查A的左或右子树
return isSame(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
private boolean isSame(TreeNode a, TreeNode b) {
// 如果子树B已经递归完成,说明所有匹配成功
if (b == null) {
return true;
}
// 如果子树B还未完成,而树A已经为空,或者两者的值不相等,则不匹配
if (a == null || a.val != b.val) {
return false;
}
// 递归比较两者的左右子树
return isSame(a.left, b.left) && isSame(a.right, b.right);
}
class Solution {
// b是否以a的某一个节点为子结构
public boolean isSubStructure(TreeNode A, TreeNode B) {
if (A == null || B == null) {
return false;
}
return isSame(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
// b是不是a的子结构
public boolean isSame(TreeNode A, TreeNode B) {
// b没有就不要求a有
if (B == null)
return true;
// b有的话a一定要有
if (A == null)
return false;
if (A.val!= B.val)
return false;
return isSame(A.left, B.left) && isSame(A.right, B.right);
}
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if (A == null||B == null)
return false;
return helper(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
public boolean helper(TreeNode A, TreeNode B) {
if (B == null)
return true;
if (A == null && B != null)
return false;
return A.val == B.val && helper(A.left, B.left) && helper(A.right, B.right);
}
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
// 判断 B 树是否是 A 树的子树或本身
if (A == null || B == null) {
return false;
}
// 判断 B 是否是 A 的本身,或者 B 是 A 的左子树;或 B 是 A 的右子树。
return compare(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
private boolean compare(TreeNode A, TreeNode B) {
if (B == null) {
return true;
}
if (A == null || A.val != B.val) {
return false;
}
// 判断 A 和 B 的子结构是否相同
return compare(A.left, B.left) && compare(A.right, B.right);
}
}
思路:判断树 B 是否是树 A 的子结构:树 B 是否和树 A 本身相同或者树 B 是否是树 A 的左子树或右子树的子结构。并且递归的比较 A 和 B 的左子树和右子树是否相同。
时间复杂度:O(n),需要遍历整个 B 树的节点。
空间复杂度:O(logn)(平均情况) 或 O(n)(最坏情况),递归调用栈的深度取决于树的高度。
共以下 22 个回答
要么A,B匹配上,要么B与A的子结构匹配。两个递归
思路:先遍历A树找到与B树根节点值相同的节点,再以B树为主判两者是否相同结构
时间O(N*N),空间O(N)
题解
原本函数:做一些临界值的判断(特别是空树不属于其他树的子结构,因为新建函数空树属于其他树的子结构(考虑到尾节点)),原本函数还要在当前节点不满足条件时,过度到左子树或者右子树继续判断
新建函数:不去考虑左子树或者右子树的过度(因为原本函数已经做了这个工作),只需要专注于判断2个子树是否相等
方法 递归判断左右子树
time O(n) space O(n)
递归,检验各个节点
时间o(mn)
空间o(n)
注意:1、递归函数B树为空(代表B树遍历完成),返回true;原函数中B树为空时(起始root为空),应该返回false;;这块边界条件自己卡了很久,需要注意。2、最开始用原函数的定义进行递归,导致找到是跟B树有相同位置结构的“子序列”树,而不是严格的子树,这块也需要注意
思路:看完解答之后才写出来的
自己写递归的时候总是对反向往回推出问题,思路转换为代码的时候会卡壳
其实本质上都是很固定的逻辑,就是根节点,左子树,右子树,分别来比较即可
逐层往下的左右子树继续寻找对比。
时间复杂度O(Mn),空间复杂度O(H)
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A null || B null) return false;
return dfs(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
}
时间:O(n)
空间:O(n)
没思路写了一个方法把自己绕进去了,看了题解,明白了,先抽出一个函数判断整个树是否有结构相同的一块,然后不断递归判断三种情况
on on
时间复杂度为O(MN),空间复杂度为O(M)。
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
// 如果任一树为空,则直接返回false
if (A null || B null) {
return false;
}
// 检查从当前节点A开始是否包含与B相同的子树结构,或者递归检查A的左或右子树
return isSame(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
}
打卡
递归,关键在于回调,如果不匹配则回调为原来的B
时间复杂度O(mn)
空间复杂度(m)
思路: 首先找到与B具有相同val的结点rootB 然后比较两棵子树 是否相同
问题:在最初为意识到存在相同元素,因此未能通过,通过添加循环结构,找到所有具有 B.val 的结点判断
代码复杂度较高
思路:判断树 B 是否是树 A 的子结构:树 B 是否和树 A 本身相同或者树 B 是否是树 A 的左子树或右子树的子结构。并且递归的比较 A 和 B 的左子树和右子树是否相同。
时间复杂度:O(n),需要遍历整个 B 树的节点。
空间复杂度:O(logn)(平均情况) 或 O(n)(最坏情况),递归调用栈的深度取决于树的高度。