先是原始解法,采用递归的方式,代码如下:
class Solution {
public boolean isSameTree(TreeNode s, TreeNode t){
if(s == null && t == null) return true;
if(s == null || t == null) return false;
return s.val == t.val && isSameTree(s.left,t.left) && isSameTree(s.right, t.right);
}
public boolean isSubtree(TreeNode s, TreeNode t) {
if(s == null && t!= null) return false;
if(s != null && t == null) return true;
else return isSameTree(s,t) || isSubtree(s.left,t) || isSubtree(s.right, t);
}
}时间复杂度O(m*n),空间复杂度O(h),h为树的高度。
上面的方法首先要遍历s的每个节点,对于每个节点,t都要遍历一次。
但是,对比两棵树是否相同,不需要一个个节点对比,而是大家有一个唯一标识拿出来对比,这样对比就需要O(1)的时间。比如可以采用把左节点,根结点,右节点的值拼接起来。因此可以采用字符串的hash函数,把整棵树的对比降到O(1)复杂度。因为在构造hash表的时候需要分别遍历一次s和t,所以算法的时间复杂度是O(m+n), 空间复杂度:由于要保存hash表,所以也是O(m+n);
代码如下:
class Solution {
Map<TreeNode, Integer> map = new HashMap<>();
public String computeHash(TreeNode s){
if(s == null) return "#";
String left = computeHash(s.left);
String right = computeHash(s.right);
String hash = left + s.val + right;
map.put(s,hash.hashCode());
return hash;
}
//构建计算hash函数的时候有技巧,要返回字符串的形式便于递归的过程中返回值。
public boolean isSub(TreeNode s, TreeNode t){
if(s == null) return false;
if(t == null) return true;
return map.get(s).equals(map.get(t)) || isSub(s.left,t ) || isSub(s.right, t);
}
public boolean isSubtree(TreeNode s, TreeNode t) {
computeHash(s);
computeHash(t);
return isSub(s,t);
}
}
京公网安备 11010502036488号