面18
题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:
采用两个方法,当头节点满足要求时,进入helper方法判定是否为子树。HasSubtree用于遍历所有可能的头节点情况。
整体采用递归的思路。
写代码的过程一直磕磕碰碰,感觉逻辑好不容易对了,但是一开始运行还是有错。提示:“运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。” 检查是否有死循环
错误代码:
public class Solution {
boolean result = false;
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if (root1 == null || root2 == null)
return false;
else {
while (root1 != null && root2 != null && result == false) { // while和递归同时出现,就是奔着死循环去的(?)
if (root1.val != root2.val) {
result = HasSubtree(root1.left, root2);
if (result == true)
break;
result = HasSubtree(root1.right, root2);
} else {
result = helper(root1, root2); // 死循环出现在这里,假设root1和root2值相等,因此进入了判断子结构环节,但后面的判断显示并非子树的情况下,这里缺少继续迭代,就会一直在这两个节点循环
}
}
return result;
}
}
public boolean helper(TreeNode root1,TreeNode root2){
if(root1!=null&&root2!=null){
if(root1.val!=root2.val){
return false;
}
else{
result = helper(root1.left,root2.left);
result = helper(root1.right,root2.right);
}
}
else if(root2==null)
return true;
return result;
}
}
修改了前面的部分,依旧错误:
测试用例:
{8,8,#,9,#,2,#,5},{8,9,#,3}
对应输出应该为:
false
你的输出为:
true
根据错误提示,直接定位到返回true的部分
boolean result = false;
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if (root1 == null || root2 == null)
return false;
else {
if (root1 != null && root2 != null && result == false) {
if (root1.val != root2.val) {
result = HasSubtree(root1.left, root2);
if (result != true)
result = HasSubtree(root1.right, root2);
} else {
result = helper(root1, root2);
if(result==false) {
root1.val = root1.val + 1; // 这里针对头节点满足要求但结果返回非子树的情况,把root1的值加1,下次迭代就会跳过这个节点,不会出现死循环
result = HasSubtree(root1,root2);
}
}
}
return result;
}
}
public boolean helper(TreeNode root1,TreeNode root2){
if(root1!=null&&root2!=null){
if(root1.val!=root2.val){
return false;
}
else{
result = helper(root1.left,root2.left);
result = helper(root1.right,root2.right); // 这里绝对是有问题的,如果前一个result已经是false,这里判true就会改变result
}
}
else if(root2==null)
return true;
return result;
}
正确答案:
使用了&&后我发现之所以前面在写代码时觉得逻辑很麻烦,就是因为没有使用&&和||,导致判定的过程很繁琐。以及没有很好地理解递归。
public class Solution {
boolean result = false;
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if (root1 == null || root2 == null)
return false;
else {
if (root1 != null && root2 != null && result == false) {
if (root1.val != root2.val) {
result = HasSubtree(root1.left, root2)|| HasSubtree(root1.right, root2);
} else {
result = helper(root1, root2);
if(result==false) {
result = HasSubtree(root1.left, root2)|| HasSubtree(root1.right, root2);
}
}
}
return result;
}
}
public boolean helper(TreeNode root1,TreeNode root2){
if(root1!=null&&root2!=null){
if(root1.val!=root2.val){
return false;
}
else{
result = helper(root1.left,root2.left)&&helper(root1.right,root2.right);
}
}
else if(root2==null)
return true;
return result;
}
}
这里稍稍改变下顺序,代码看起来也会更有“逻辑”和简洁
public static boolean HasSubtree(TreeNode root1, TreeNode root2) {
boolean flag = false;
if (root1 != null && root2 != null) {
if (root1.val == root2.val)
flag = helper(root1, root2);
if (!flag)
flag = HasSubtree(root1.left, root2);
if (!flag)
flag = HasSubtree(root1.right, root2);
}
return flag;
}
public boolean DoesTree1HaveTree2(TreeNode root1,TreeNode root2){
if(root1 == null && root2 != null) return false;
if(root2 == null) return true;
if(root1.val != root2.val) return false;
return DoesTree1HaveTree2(root1.left, root2.left) && DoesTree1HaveTree2(root1.right, root2.right);
}
再加一种方法,HasSubTree中不用递归做,直接前序遍历A树,当找到子树时则停止遍历
import java.util.*;
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean result = false;
if(root1==null||root2==null)
return result;
TreeNode temp;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root1);
while(!stack.isEmpty()&&result==false){
temp = stack.pop();
if(temp.val==root2.val)
result = helper(temp,root2);
if(temp.right!=null)
stack.push(temp.right);
if(temp.left!=null)
stack.push(temp.left);
}
return result;
}
public boolean helper(TreeNode root1,TreeNode root2){
if(root2==null)
return true;
if(root1==null)
return false;
if(root1.val!=root2.val)
return false;
if(root1.val==root2.val)
return helper(root1.left,root2.left)&&helper(root1.right,root2.right);
return true;
}
}