输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
方法一(DFS深度优先前序遍历,迭代)分析:
既然是要找到A树中是否有B树这样子树,即找到A树中的子结构nA,判断其和B树相同,可以分为两个步骤:
(1)遍历A树找到一个节点nA,其节点和树B的头节点相同,如果找不到nA,就说明,B树不是A树的子结构
(2)(递归)将nA与B树进行节点遍历,检查所有节点是否相同
具体做法:
- step 1:因为空树不是任何树的子树,所以要先判断B树是否为空树。
- step 2:当A树为空节点,但是B树还有节点的时候,不为子树,但是A树不为空节点,B树为空节点时可以是子结构。(B可以为A树的一小段结构,不必从头到尾都一样,子结构和子树概念不同)
- step 3:每次递归比较A树从当前节点开始,是否与B树完全一致,同步前序遍历。
- step 4:A树自己再前序遍历进入子节点,当作子树起点再与B树同步遍历。
- step 5:以上情况任意只要有一种即可。
class Solution { public: bool isSubStructure(TreeNode* A, TreeNode* B) { if(A==nullptr||B==nullptr) return false; bool res = recur(A, B) ; bool left = isSubStructure(A->left, B); bool right = isSubStructure(A->right, B); return left||right||res ; } private: bool recur(TreeNode* A, TreeNode* B) { //B空直接返回(不管A是否为空),都说明B对完了,是A的子结构 if(B == nullptr) return true; //B不空,A空了,或者节点对不上,都失败 if(A == nullptr || A->val != B->val) return false; //迭代遍历 return recur(A->left, B->left) && recur(A->right, B->right); } };
class Solution { public: bool recursion(TreeNode* root1, TreeNode* root2){ //当一个节点存在另一个不存在时 if(root1 == NULL && root2 != NULL) return false; //两个都为空则返回 if(root1 == NULL || root2 == NULL) return true; //比较节点值 if(root1->val != root2->val) return false; //递归比较子树 return recursion(root1->left, root2->left) && recursion(root1->right, root2->right); } bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { //空树 if(pRoot2 == NULL) return false; //一个为空,另一个不为空 if(pRoot1 == NULL && pRoot2 != NULL) return false; if(pRoot1 == NULL || pRoot2 == NULL) return true; //递归比较 bool flag1 = recursion(pRoot1, pRoot2); //递归树1的每个节点 bool flag2 = HasSubtree(pRoot1->left, pRoot2); bool flag3 = HasSubtree(pRoot1->right, pRoot2); return flag1 || flag2 || flag3; } };
方法二(BFS层遍历,迭代)分析:
既然是要找到A树中是否有B树这样子树,即找到A树中的子结构nA,判断其和B树相同,可以分为两个步骤:
(1)层序遍历A树找到一个节点nA,其节点和树B的头节点相同,如果找不到nA,就说明,B树不是A树的子结构(2)开始同步层次遍历比较以这个nA节点为根的树中是否出现了B树的全部节点。因为我们只考虑B树的所有节点是否在nA树中全部出现,那我们就以B树为基,再进行一次层次遍历,nA树从那个节点开始跟随B树一致进行层次遍历就行了,比较对应的每个点是否相同,或者B树是否有超出A树没有的节点
class Solution { public: bool isSubStructure(TreeNode* A, TreeNode* B) { if(A==nullptr||B==nullptr)return false; queue<TreeNode*> que; que.push(A); while(!que.empty()){ TreeNode* head = que.front(); que.pop(); if(head->val==B->val){ if(bfs(head,B)==true){ return true; } } if(head->left)que.push(head->left); if(head->right)que.push(head->right); } return false; } private: //进入到这个函数的前提是nA和B的头节点相同 bool bfs(TreeNode* nA,TreeNode* B){ queue<TreeNode*> quenA; queue<TreeNode*> queB; quenA.push(nA); queB.push(B); while(!queB.empty()){ TreeNode* nodeA = quenA.front(); TreeNode* nodeB = queB.front(); quenA.pop(); queB.pop(); //如果遍历过程中nodeA空,或者节点对不上,就返回; if(nodeA == nullptr||nodeA->val!=nodeB->val) return false; //反之将剩余节点继续遍历 if(nodeB->left!=nullptr){ queB.push(nodeB->left); //A跟着走 quenA.push(nodeA->left); } if(nodeB->right!=nullptr){ queB.push(nodeB->right); //A跟着走 quenA.push(nodeA->right); } } return true; } };