今天起再开一个系列,讲我在leetcode上的每天刷的算法题目
题目描述
给你两棵二叉树 root
和 subRoot
。检验 root
中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
。
二叉树 tree
的一棵子树包括 tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。
定义
```CPP
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
基本的思路是把树序列化,转化为字符串,再用std::string的搜索功能完成题目。
序列化…?
我们时常要对比两个数据结构是否是相等的。那自然衍生出了下面一个问题,**如何把树这个有复杂空间的结构变成一个序列?**要知道,顺序的序列的对比,可比复杂结构容易多了。这里我们借助深度优先算法(DFS)这是先访问深层的子树,再返回上一层的子节点(我们可以使用递归容易的实现这一点)
// 序列化函数
string serialize(TreeNode* root) {
if (!root) return "#"; // 空节点用#表示
return to_string(root->val) + " " +serialize(root->left) +" "+ serialize(root->right);
}
- 为何要有
+ " " +
?很简单,要把不同位置的元素隔开 3 -> 11 ;2 (根为3,左值为11 ,右值为2)的树和
31-> 1;2是很不一样的,但是如果不隔开元素两者都是311##2##
就变成一样的了,这显然不行
-好像…解决了?
错解
class Solution {
public:
string serialize(TreeNode* root) {
if (!root) return "#"; // 空节点用#表示
return to_string(root->val) +" "+ serialize(root->left) +" "+ serialize(root->right);
}
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
string treestr=serialize(root);
string subtreestr=serialize(subRoot);
size_t findloc=treestr.find(subtreestr);
if (findloc != std::string::npos) {
return true;
} else {
return false;
}
}
};
错因何在?
输入root=[12],subroot=[2],生成的序列是:12 # #
,而subroot的序列是:2 # #
,从字符串的角度看,确实是重复了一部分,但是subroot和root并不是子树的关系,可见,我们对元素的开始和结束需要标记
// 序列化函数
string serialize(TreeNode* root) {
if (!root) return "#"; // 空节点用#表示
return "(" + to_string(root->val) +")" + serialize(root->left) + serialize(root->right);
}
这是序列化的示例
Serialized tree: (1)(2)(40)##(5)##(13)##
##正解
class Solution {
public:
// 序列化函数
string serialize(TreeNode* root) {
if (!root) return "#"; // 空节点用#表示
return "(" + to_string(root->val) +")" + serialize(root->left) + serialize(root->right);
}
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
string treestr=serialize(root);
string subtreestr=serialize(subRoot);
size_t findloc=treestr.find(subtreestr);
if (findloc != std::string::npos) {
return true;
} else {
return false;
}
}
};
效果
虽然不是最快的,但是我们的代码结构绝对简单易懂。♪(´▽`)