Update:
The best solution should be:
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null) return true;
if(p==null||q==null) return false;
return isSameTree(p.left, q.left)&&isSameTree(p.right, q.right)&&(p.val==q.val);
}
Update:
Thank you all, I know those other solutions you told me, but my question is that why my solution doesn't work. Is it because that I ignore some return values? Thank you!
I have written a code for determining whether two binary trees are the same, I used recursive method to search through the tree, but this code sometimes didn't work, could you please help me to figure it out?
Thanks a lot!
Here's the code:
/*Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p!=null){
if(q!=null&&p.val==q.val){
isSameTree(p.left, q.left);
isSameTree(p.right, q.right);
}
else return false;
}else{
if(q!=null) return false;
}
return true;
}
Input:
[10,5,15]
[10,5,null,null,15]
Output:
true
Expected:
false
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p!=null){
if(q!=null&&p.val==q.val){
if(!isSameTree(p.left, q.left)) return false;
if(!isSameTree(p.right, q.right)) return false;
return true;
}
else return false;
}else{
if(q!=null) return false;
}
return true;
}
I'm assuming you have a get method to retrieve data.One way you can solve is to let isSameTree methods to accept null values and then compare.
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == q) {
return true;
}
if (p == null || q == null) {
return false;
}
return p.get().isSameTree(q.get()) &&
isSameTree(p.left(), q.left()) &&
isSameTree(p.right(), q.right());
}
Another way is the following:
public boolean isSameTree(TreeNode p, TreeNode q)
{
if (p == null && q == null)
return true;
if (p != null && q != null)
return (p.get == q.get
&& isSameTree(p.left, q.left)
&& isSameTree(p.right, q.right));
return false;
}
You are just calling isSameTree for the child trees, but not checking their return values. Concise and correct version:
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == q) { //Will accept null == null
return true;
}
return p != null && q != null && p.val == q.val &&
isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
Also, #duffymo was incorrect stating you needed to use .equals() instead of ==. You are comparing the val's, which are primitives.
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null)
return true;
if (p != null && q != null)
return (p.val == q.val
&& isSameTree(p.left, q.left)
&& isSameTree(p.right, q.right));
return false;
}
}
Related
I'm trying to determine if one tree (t) is a subtree of another tree (s).
This is a link to the leetcode which explains the problem thoroughly:https://leetcode.com/problems/subtree-of-another-tree/
My approach: I have one function that does a dfs on s and compares each node to the root of t in another function to determine if t is a subtree of s
My solution doesn't work for when s=[1,1] and t=[1], although I think it should be working. Could you please look at my code and explain what's wrong.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
/* dfs on s, at each node running a compare tree function for s at that node and
root of t*/
if(s == null || t == null) {
return false;
}
return dfs(s, t);
}
public static boolean dfs(TreeNode s, TreeNode t) {
if(s == null) {
return false;
}
if(s.val == t.val) {
return isSameTree(s, t);
}
return dfs(s.left, t) || dfs(s.right, t);
}
public static boolean isSameTree(TreeNode s, TreeNode t) {
if(s == null || t == null) {
return s == t;
}
if(s.val != t.val) {
return false;
}
return isSameTree(s.left, t.left) && isSameTree(s.right, t.right);
}
}
You need to check for all nodes of s if t is a subtree of that node or not. If you stop at first node while performing dfs on s and its value is same as root of t but subtrees are different, there might be some another node of tree s whose value and subtree both are same as t.
In other words, you need to repeat your 1st step (perform dfs on s and compare each node of s to the root of t) until you have checked all nodes of s (dfs is complete on s) or found that t is subtree of s.
s t
(1) (1)
/
(1)
Do not return from root of s just because of same values of root of s and t. If t is not subtree of that node, keep doing dfs to find another node whose value and subtree both are same as t (left child of root of s in this case).
For more clarity, below is your code with corrected part highlighted:
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
/* dfs on s, at each node running a compare tree function for s at that node and
root of t*/
if(s == null || t == null) {
return false;
}
return dfs(s, t);
}
public static boolean dfs(TreeNode s, TreeNode t) {
if(s == null) {
return false;
}
// ==== Corrected below if ====
// apart from s.val == t.val, if isSameTree(s, t) is true at this
// point, return true; otherwise keep doing dfs for rest of the tree s
// other same value node of s can be the answer
if(s.val == t.val && isSameTree(s, t)) {
return true;
}
return dfs(s.left, t) || dfs(s.right, t);
}
public static boolean isSameTree(TreeNode s, TreeNode t) {
if(s == null || t == null) {
return s == t;
}
if(s.val != t.val) {
return false;
}
return isSameTree(s.left, t.left) && isSameTree(s.right, t.right);
}
}
Looks pretty good! Almost there!
This'd pass:
public class Solution {
public static final boolean isSubtree(
final TreeNode s,
final TreeNode t
) {
if (s == null) {
return false;
}
if (checkNextLevel(s, t)) {
return true;
}
return isSubtree(s.left, t) ||
isSubtree(s.right, t);
}
private static final boolean checkNextLevel(
final TreeNode s,
final TreeNode t
) {
if (s == null && t == null) {
return true;
}
if (
(s == null || t == null) ||
(s.val != t.val)
) {
return false;
}
return checkNextLevel(s.left, t.left) &&
checkNextLevel(s.right, t.right);
}
}
I wrote the following code but I only get partial credit and I'm not 100% sure of how to fix it.
public boolean MBTsame(BinNode root1, BinNode root2)
{
if (root1 == root2 ) {
return true;
}
else if(root1 != null && root2 != null){
return true;
}
else {
return false;
}
}
I know this may be a duplicate post, but I would submit my own code to your attention.
I wrote the following recursive procedure, but I would like to optimize it.
I would like to stop the treeCompare method as soon as I find a node different from other, instead of comparing all nodes.
Thanks in advance for your help.
This is my thin Node class:
public class Node {
public Node father;
public Node left;
public Node right;
}
And this is my comparator method:
private boolean treeCompare(Node firstNode, Node secondNode) {
if (firstNode == null && secondNode == null)
return true;
else if (firstNode == null || secondNode == null)
return false;
boolean isLEquals = treeCompare(firstNode.left, secondNode.left);
boolean isREquals = treeCompare(firstNode.right, secondNode.right);
return firstNode.equals(secondNode) && isLEquals && isREquals;
}
private boolean treeCompare(Node firstNode, Node secondNode) {
if (firstNode == secondNode)
return true;
if (firstNode == null || !firstNode.equals(secondNode))
return false;
return treeCompare(firstNode.left, secondNode.left) && treeCompare(firstNode.right, secondNode.right);
}
I've made my own Tree class and I trying to check if two trees are identical. But the problem here is I'm using this call :
Tree myTree = new Tree();
Tree mySecondTree = new Tree();
myTree.isIdentical(myTree, mySecondTree);
It's kind of odd to pass it this way, I want to pass it this way :
myTree.isIdentical(mySecondTree);
isIdentical function :
class Tree<T>{
T data;
Tree left;
Tree right;
Tree(T data){
this.data = data;
}
public boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}
}
I tried using Stack, but I'm kind of stuck on this
Since you want to execute it this way
myTree.isIdentical(mySecondTree);
You could do this
public boolean isIdentical(Tree t2){
Tree t1 = this;
return isIdentical(t1, t2);
}
private boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}
Your data-structure allows you to call the modified isIdentical(Tree<T>) method in the left and right child nodes after a few checks. Remember that the parent, right-child and left-child are all different Tree node instances in your code.
public boolean isIdentical(Tree<T> that) {
if (this == that)
return true;
if (that == null)
return false;
//check the equality of the current node's data for both this and that.
if (this.data == that.data || (this.data != null && this.data.equals(that.data))) {
//check the left hand side of the current node for both this and that.
if ((this.left == null && that.left == null
|| this.left != null && this.left.isIdentical(that.left))
//check the right hand side of the current node for both this and that.
&& (this.right == null && that.right == null
|| this.right != null && this.right.isIdentical(that.right))) {
return true;
}
}
return false;
}
You could stay with a recursion and make isIdentical(myTree, Othertree) private. Then wrap it inside a method IsIdentical(otherTree) that calls the method with two arguments suppling this (refrence to the current object) as the first parameter.
I need to compare two binary search trees and see if they are equal or not.
I developed following code that uses recursion.
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1.getNodeData() != n2.getNodeData())
return false;
else
{
if(n1.left != null && n2.left != null)
compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
compareTrees(n1.right, n2.right);
}
return true;
}
The problem is that if two nodes are not equal, the method will return false but because I use recursion, the return value will be overridden to true no matter what. I have been stuck with this problem for all day and nothing worked for me. I searched online but I didn't find anything relevant to my code.
Is there any way to break from all nested methods and return value to the first method?
You need to return the result of the subtree comparison:
boolean b1, b2;
if(n1.left != null && n2.left != null)
b1 = compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
b2 = compareTrees(n1.right, n2.right);
return b1 && b2;
But why not just deal with nulls before-hand?
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if (n1 == null || n2 == null)
return n1 == n2; // i.e. both null
if (n1.getNodeData() != n2.getNodeData())
return false;
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
}
I would do it changing the order:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
boolean equalLeft = false;
boolean equalRight = false;
if(n1.getNodeData() == n2.getNodeData())
{
if(n1.left != null && n2.left != null){
equalLeft = compareTrees(n1.left, n2.left);
} else{
equalLeft = true;
}
if(n1.right != null && n2.right != null){
equalRight = compareTrees(n1.right, n2.right);
} else{
equalRight = true;
}
return equalLeft && equalRight;
} else{
return false;
}
}
Try to face the problem avoiding null values and using equals() method instead of == comparison for your nodes. I shoud do it this way:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2){
//avoid nulls :TDD
if (n1==null && n1==n2)
return true;
if ((n1==null && n2!=null) || (n2==null && n1!=null))
return false;
//ensure logic without nulls, comparing with equals() method
boolean areEquals = n1.getNodeData().equals(n2.getNodeData());
//compare left
areEquals = areEquals && compareTrees(n1.left, n2.left);
//if still equals, compare right
if(areEquals) areEquals = areEquals && compareTrees(n1.right, n2.right);
return areEquals;
}
Effectively, your code could reduce to:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1==null || n2==null) return n1==n2;
return (n1.getNodeData()==n2.getNodeDate()) && compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right)
}
I will tell you couple of problems your code has.
Termination criteria when root is null (it will always happen in the end).
Return statements in recursive calls. You are always returning the true in the end.
PS: If you add NULL checks (explained in 1), you need not to add null checks in the subsequent recursive calls. Now the second half of your code will look like:
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);