【LeetCode-树】另一个树的子树
题目描述
给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
示例:
给定的树 s:
3
/ \
4 5
/ \
1 2
给定的树 t:
4
/ \
1 2
返回 true,因为 t 与 s 的一个子树拥有相同的结构和节点值。
给定的树 s:
3
/ \
4 5
/ \
1 2
/
0
给定的树 t:
4
/ \
1 2
返回 false。
题目链接: https://leetcode-cn.com/problems/subtree-of-another-tree/
思路1
使用和树的子结构一样的解法。代码如下:
/**
* 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) {}
* };
*/
class Solution {
public:
bool isSubtree(TreeNode* s, TreeNode* t) {
if(t==nullptr) return true;
if(s==nullptr) return false;
return isSame(s, t) || isSubtree(s->left, t) || isSubtree(s->right, t);
}
bool isSame(TreeNode* s, TreeNode* t){
if(s==nullptr && t==nullptr) return true;
if(s==nullptr || t==nullptr) return false;
if(s->val==t->val){
return isSame(s->left, t->left) && isSame(s->right, t->right);
}else return false;
}
};
思路2
遍历树 s 中的每个节点,判断以 s 中以当前结点为根的树是否和 t 相同。如果相同,则说明 t 是 s 的子树。遍历可以使用 dfs,也可以使用 bfs,这里使用 dfs。代码如下:
/**
* 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) {}
* };
*/
class Solution {
public:
bool ans = false;
bool isSubtree(TreeNode* s, TreeNode* t) {
dfs(s, t);
return ans;
}
/*将s中每个节点为根节点的树与t进行比较*/
void dfs(TreeNode* s, TreeNode* t){
if(s==nullptr) return;
if(compare(s, t)){
ans = true;
return;
}
dfs(s->left, t);
dfs(s->right, t);
}
/*比较以s为根的树和以t为根的树是否相同*/
bool compare(TreeNode* s, TreeNode* t){
if(s==nullptr && t!=nullptr) return false;
if(s!=nullptr && t==nullptr) return false;
if(s==nullptr && t==nullptr) return true;
if(s->val==t->val) return compare(s->left, t->left) && compare(s->right, t->right);
else return false;
}
};
- 时间复杂度:O(|s|*|t|)
|s|表示 s 中节点的个数,|t| 同理。 - 空间复杂度:O(max(height_s, height_t))
空间复杂度是两棵树中较高的那棵树的树高。
思路3
记录两棵树的 dfs 序列,然后判断 t 的 dfs 序列是否在 s 的 dfs 序列中。如果在,则说明 t 是 s 的子树,否则,t 不是 s 的子树。注意这里要用 dfs 序列,不能用 bfs 序列,而且 dfs 序列中要记录空节点(下面代码中使用#
表示空节点),因为记录了空节点的 dfs 序列才能唯一确定一棵树。
代码如下:
/**
* 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) {}
* };
*/
class Solution {
public:
bool isSubtree(TreeNode* s, TreeNode* t) {
vector<string> sNodes;
vector<string> tNodes;
dfs(s, sNodes);
dfs(t, tNodes);
if(compare(sNodes, tNodes)) return true;
else return false;
}
void dfs(TreeNode* root, vector<string>& nodes){
if(root==nullptr){
nodes.push_back("#");
return;
}
nodes.push_back(to_string(root->val));
dfs(root->left, nodes);
dfs(root->right, nodes);
}
bool compare(vector<string> v1, vector<string> v2){
int i1 = 0, i2 = 0;
while(i1<v1.size() && i2<v2.size()){
if(v1[i1]==v2[i2]){
if(i2==v2.size()-1) return true;
else{
i1++;
i2++;
}
}else{
i1 = i1-i2+1;
i2 = 0;
}
}
return false;
}
};
这里用的是普通的字符串匹配算法,如果用 KMP 算法会更快。
- 时间复杂度:O(|s|*|t|)
|s|表示 s 中节点的个数,|t| 同理。 - 空间复杂度:O(|s|+|t|)
纪念
这是我刷 LeetCode 的第 100 题,继续加油!