572.另一棵树的子树

本文介绍了如何在二叉树中判断链表是否存在作为其子结构的问题,通过isSubtree函数检查结构和值的一致性,以及在处理链表子链问题时对dfs函数的调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

572.另一棵树的子树

力扣572. 另一棵树的子树

今天在看面经的时候看到一个题,大意是:判断链表有没有在二叉树中出现过。想起好像力扣有一道类似的,就想都总结下。

分析

对于树类型的题,要注意从根节点分析(每个节点都是它那颗子树的根节点)。

在这里插入图片描述

要判断是否是子树,即是判断结构和值是否相同。那么我们需要从结构和值方面考虑:

  • 如果rootsubRoot都为null,满足
  • 如果rootsubRoot其中一个为null,另一个不为null,不满足
  • 如果rootsubRoot都不为空,若值相等则该节点满足,继续判断左右的节点;否则,从root的左右子树中继续找

我们使用isSubtree(root, subRoot)来判断subRoot是否是root为根的树的子树;使用dfs(root, subRoot)来判断root为根的子树和subRoot为根的子树是否一致(结构和值相同)。

对于isSubtree(root, subRoot)函数,返回true的条件是:

  • dfs(root, subRoot)返回true,如上图中root = 4时,即以当前节点为根的子树和subRoot一致
  • 或者,root的左子树存在和subRoot一致的子树
  • 或者,root的右子树存在和subRoot一致的子树

对于dfs(root, subRoot)函数,返回true的条件是:

  • root为根的子树和subRoot为根的子树结构一致(可以理解为有相同的分叉数)

  • rootsubRoot的值相等,并且左子树和右子树中的值也分别相等

最坏情况下,对于每一个root上的点,都需要做一次深度优先搜索来和subRoot匹配,时间复杂度为O(nm)nroot的节点个数,msubRoot的节点个数。(想象两个只有一点差别的树,树中节点值都为1)

依照上面的分析,具体代码如下:

class Solution {
public:
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        if(!root && !subRoot) 
            return true;
        if(!root || !subRoot) 
            return false;
        
        return dfs(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
    }
    bool dfs(TreeNode* root, TreeNode* subRoot) {
        if(!root && !subRoot)
            return true;
        if(!root || !subRoot)
            return false;
        return root->val == subRoot->val && dfs(root->left, subRoot->left) && dfs(root->right, subRoot->right);
    }
};

判断子链

即判断二叉树root是否包含链表subRoot。由于没地方做测试,这里用树模拟链表,树的左指针模拟链表的next指针,例如链表[4,2,0]用树表示为:

在这里插入图片描述

与上面的二叉树类似,isSubtree()函数不用更改,需要更改的是dfs()函数部分。因为只要左右子树有一个和链表一致即可,且链表只有一个方向(left),所以核心代码更改如下:

bool dfs(TreeNode* root, TreeNode* subRoot) {
    ...
        
    return root->val == subRoot->val && (dfs(root->left, subRoot->left) || dfs(root->right, subRoot->left));
}

在力扣上的测试结果如下(代码测试不完全,但是主要是体现思路),修改dfs函数逻辑后,返回true代表root中存在于subRoot一致的子链:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值