LeetCode——Subtree of Another
# 572
Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree s could also be considered as a subtree of itself.
Example 1:
Given tree s:
3
/ \
4 5
/ \
1 2
Given tree t:
4
/ \
1 2
Return true, because t has the same structure and node values with a subtree of s.
Example 2:
Given tree s:
3
/ \
4 5
/ \
1 2
/
0
Given tree t:
4
/ \
1 2
Return false.
这题的目的是判断一个数是否是另一棵树的子数。从第二个例子可以看出,子树必须是完整的,不能是中间一部分,必须是叶节点。
这题显然可以用递归写,大部分树的问题,都可以用递归的方法解决。其实和前面写过的一题对称树也没大多差别。代码也很容易懂,递归的话,多使用的话,理清思路,就很容易掌握了。
- C++
/**
* 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 isSubtree(TreeNode* s, TreeNode* t) {
if(!s)
return false;
if(is_Sub(s,t))
return true;
return isSubtree(s -> left,t) || isSubtree(s -> right,t);
}
bool is_Sub(TreeNode* s,TreeNode* t){
if( !s && !t)
return true;
if( !s || !t)
return false;
if(s -> val != t -> val)
return false;
return is_Sub(s -> left,t -> left) && is_Sub(s -> right,t -> right);
}
};
- Java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if (s == null)
return false;
if (isSame(s, t))
return true;
return isSubtree(s.left, t) || isSubtree(s.right, t);
}
private boolean isSame(TreeNode s, TreeNode t) {
if (s == null && t == null)
return true;
if (s == null || t == null)
return false;
if (s.val != t.val)
return false;
return isSame(s.left, t.left) && isSame(s.right, t.right);
}
}
- Python
**# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def isSubtree(self, s, t):
"""
:type s: TreeNode
:type t: TreeNode
:rtype: bool
"""
if not s or not t: return not s and not t
if self.check(s, t): return True
return self.isSubtree(s.left, t) or self.isSubtree(s.right, t)
def check(self, s, t):
if not s or not t: return not s and not t
if s.val != t.val: return False
return self.check(s.left, t.left) and self.check(s.right, t.right)**
看到其他一些人的解法,有一种思路是对s和t两棵树分别进行序列化,各生成一个字符串,如果t的字符串是s的子串的话,就说明t是s的子树。其中一个注意的地方是,为了避免前缀,在每个节点值前面都加一个字符。代码如下。
- C++
/**
* 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 isSubtree(TreeNode* s, TreeNode* t) {
ostringstream os1, os2; //构造一个字符串,使用ostringstream类,该类能够根据内容自动分配内存
serialize(s, os1);
serialize(t, os2);
return os1.str().find(os2.str()) != string::npos;//
}
void serialize(TreeNode* node, ostringstream& os) { //这里的序列化使用的是前序遍历
if (!node) os << ",#";
else {
os << "," << node->val;
serialize(node->left, os);
serialize(node->right, os);
}
}
};
npos可以表示string的结束位子,是string::type_size 类型的,也就是find()返回的类型。find函数在找不到指定值得情况下会返回string::npos。
关于ostringstream类,也简单的描述一下。
C++提供的流(stream)包括三种类型:用于控制台输入/输出的流、用于文件操作的文件流和用于字符串处理的字符串流。
(1) 基于控制台的流
istream:用于从流中读取内容;
ostream:用于将内容写到数据流中;
iostream:用于对流进行读写,从istream和ostream派生;
它们包含在iostream头文件中。
(2) 用于文件读取/写入的文件流
ifstream:用于从文件中读取,由istream派生而来;
ofstream:用于将内容写到文件中去,由ostream派生而来;
fstream:实现文件的读写操作,有iostream派生而来;
它们包含在头文件fstream中。
(3) 基于字符串I/O操作的字符串流
istringstream:实现从字符串(string)对象中读取内容,由istream派生而来;
ostringstream:实现将内容写到字符串(string)对象中,由ostream派生而来;
stringstream:实现string对象的读写操作,由iostream派生而来;
它们包含在头文件sstream中。
这种解法的Python写法
- Python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def isSubtree(self, s, t):
"""
:type s: TreeNode
:type t: TreeNode
:rtype: bool
"""
def preorder(node):
if not node:
return "$"
return "^" + str(node.val) + "#" + preorder(node.left) + preorder(node.right)
print preorder(s)
print preorder(t)
return preorder(t) in preorder(s)
还看到一种解法,使用了hash树,运行时间非常的短。但相对复杂一点,记录下来,学习一下。
- Python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
from hashlib import md5
class Solution(object):
def isSubtree(self, s, t):
def treehash(root):
h = md5(treehash(root.left) + str(root.val) + treehash(root.right)).hexdigest() if root else ''
hashes.append(h)
return h
hashes = []
h = treehash(t)
hashes = []
treehash(s)
return h in hashes
def isSubtree(self, s, t):
def string(root):
return '(%d,%s,%s)' % (root.val, string(root.left), string(root.right)) if root else ''
return string(t) in string(s)
def isSubtree(self, s, t):
def tuplify(root):
return (root.val, tuplify(root.left), tuplify(root.right)) if root else None
return str(tuplify(t)) in str(tuplify(s))
本文探讨了LeetCode上的经典题目572:如何判断一棵树是否为另一棵树的子树。提供了多种解决方案,包括递归比较、字符串序列化对比以及使用哈希树的方法。
1955

被折叠的 条评论
为什么被折叠?



