-
题目:
给定两棵二叉树A和B,判断B是不是A的子结构;
空树不是任何树的子结构; -
思路:
1.递归:O(mn):m是A树的节点个数,n是B树的节点个数,遍历A的所有节点O(m),尝试将A的每个节点都作为根去作匹配工作O(n),空间应该是O(m):当树 A和树 B 都退化为链表时,递归调用深度最大。当m≤n 时,遍历树 A 与递归判断的总递归深度为 m ;当 m>n 时,最差情况为遍历至树 A 叶子节点,此时总递归深度为 m:
通过递归调用isSubStructure的方式,遍历A的所有节点去尝试与B匹配,去寻找A中的那个目标根结点;
对于A的每一个以p1为根的子树是不是与B匹配,也用递归isSame的方式去对比;
/**ch
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
private:
//空 空 1
//空 不空 0
//不空 空 1
//不空 不空 递归判断二者的左孩子和右孩子
bool isSame(TreeNode* p1, TreeNode* p2) {//判断子树p1与子树p2是否匹配
if (!p2) return true;//空 空 和 不空 空, 即子树p2成功到底
else if (!p1) return false;//空 不空, 即p2还没匹配完成,主树p1就到底了
//不空 不空
else if (p1->val != p2->val) return false; //当前节点已经不匹配
return isSame(p1->left, p2->left) && isSame(p1->right, p2->right);//当前节点匹配,就去递归判断左右子树都匹配才行
}
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {//在子树A中寻找一个与子树B匹配的目标根
if (!A || !B) return false;
if (isSame(A, B)) return true;//目标根是A
//递归的在A的左右子树中寻找与B匹配的目标根
return isSubStructure(A->left, B) || isSubStructure(A->right, B);//只要能找到一个目标根即可
}
};
- 总结:
① 对于树的题,在使用递归时,只需要想清楚当前函数的作用,以及主问题如何分解为子问题即可,不要一直往深处想;
② 本题的根节点struct中,根节点值是用int表示的,因此可以直接比较;若用float或double表示的,由于浮点数在计算机中表示时具有不精确性,因此需要专门设计一个equal函数去做比较工作:例如二者误差在0.00000001范围内,就认为它们相等;