主要内容 #
- 问题描述
- 求解思路
- 参考代码
1.问题描述 #
输入两棵二叉树A和B,判断B是不是A的子结构。
例如图1中的两棵二叉树,有一部分子树的结构和B是一样的,因此B是A的子结构。
2.求解思路 #
要查找A树中是否存在和B一样的子树,我们可以分两步:
- 在树A中找到和树B的根节点的值一样的节点R;
- 判断树A中以R为根节点的子树是不是包含和树B一样的结构。
以上面图1的两棵树为例来详细分析这个过程。首先试着在树A中找到值为8(树B根节点的值)的节点。从树A得根节点开始遍历,我们发现它的根节点的值就是8。接着判断树A的根节点下面的子树是不是含有和树B一样的结构,如图2所示。在树A中,根节点的左子树的值是8,而树B的根节点的左节点是9,对应的两个节点不同。
因此我们仍需要遍历树A,接着查找值为8的节点。我们在树的第二层找到了一个值为8的节点,然后进行第二步判断,即判断这个节点下面的子树是否含有和树B一样的结构,如图3所示。于是遍历这个节点下的子树,先后得到两个子节点9和2,这和树B的结构完全相同。此时我们在树A中找到了一棵和树B结构一样的子树,因此树B是树A的子结构。
第一步在树A中查找与跟节点的值一样的节点,这实际上就是树的遍历,可以用递归的方法去遍历,也可以用循环的方法去遍历。递归的代码实现比较简洁。
3.参考代码 #
#include <iostream> #include <queue> using namespace std; struct TreeNode { double val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; // 递归 /* 时间复杂度: O( nm ),空间复杂度:O( m ) */ class Solution { public: bool isSubStructure(TreeNode* A, TreeNode* B) { bool res = false; // 此处相当于「前序」遍历 if ( A != nullptr && B != nullptr ) { if ( A->val == B->val ) // 根节点值相等 res = DoesTree1HaveTree2( A, B ); if ( !res ) // 遍历 A 的左子树 res = isSubStructure( A->left, B ); if ( !res ) // 遍历 A 的右子树 res = isSubStructure( A->right, B ); } return res; } bool DoesTree1HaveTree2( TreeNode* A, TreeNode* B ) { if ( B == nullptr ) return true; if ( A == nullptr ) // 此时,B != nullptr return false; if ( A->val != B->val ) return false; return DoesTree1HaveTree2( A->left, B->left ) && DoesTree1HaveTree2( A->right, B->right ); } };