题目
LCR 143. 子结构判断
一种错误的解法
- 根据观察,我意识到二叉树的先序遍历的序列可能是唯一的,那么如果 tree2 是 tree1 的子结构,其先序遍历序列应该就是 tree1 先序遍历序列的子序列,可以进行子序列的匹配,如果匹配上了就是子结构
- 但实际上,子结构和子树并不是同一个概念,子结构相当于原来树的一部分,而子树是在相当于原来树的一部分的同时,其不能有其他子节点,只能有父结点
- 比如下面这种输入,Tree2 确实是 Tree1 的一部分,但是不是其子树,两棵树的先序遍历结果并不匹配
Tree1:[10,12,6,8,3,11],先序遍历:[10,12,8,3,6,11]
Tree2:[10,12,6,8],先序遍历:[10,12,8,6]
- 所以这种解法是错误的,在此贴上错误代码
/**
* 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 {
vector<int> va, vb;
public:
//先序遍历
void preorder_Traversal(TreeNode* root, vector<int>& v){
if(!root) return;
v.push_back(root->val);
preorder_Traversal(root->left, v);
preorder_Traversal(root->right, v);
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(!B) return false;
//得到两棵树先序遍历的结果
preorder_Traversal(A, va);
preorder_Traversal(B, vb);
if(vb.size()>va.size()) return false;
//开始进行序列匹配
for(int i=0; i<=va.size()-vb.size(); ++i){
auto ita = va.begin()+i, itb=vb.begin();
while(*ita==*itb){
++ita;
++itb;
if(itb==vb.end()) return true;//B树匹配完成
}
}
return false;
}
};
正确解法:
思想
- 子结构可能与当前节点匹配,或者与当前节点的左子节点匹配,或者与当前节点的右子节点匹配
- 在匹配过程中,使用递归思想,不断匹配。如果匹配成功,则子结构被遍历到空节点;如果有节点不匹配,则匹配失败;如果直到 Tree1 都遍历完成还没匹配上,则也是匹配失败
/**
* 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 {
public:
bool recur(TreeNode* A, TreeNode* B){
if(!B) return true;//B树已经越过了叶子节点,匹配成功,返回(最终是否成功由B树的其他部分尝试匹配后确定)
if(!A || A->val!=B->val) return false;//已经越过了A的叶子节点,或者A与B节点值不匹配,则匹配失败
//本节点匹配相同,AB可能是从此节点开始匹配,则查看其左右子树是否匹配
return recur(A->left, B->left) && recur(A->right, B->right);
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
//AB节点要都非空,并且B与A/A->left/A->right可能开始匹配(递归)
return (A && B) && (recur(A, B) || isSubStructure(A->left, B) ||isSubStructure(A->right, B));
}
};