I'm creating a binary search tree project, and one of the questions is to create 2 trees and check if they're equal or not. When I implement the method, I keep getting
firstTree and secondTree are equal. Here's the relevant code:
BstTest2 firstTree = new BstTest2();
firstTree.addNode(50, "Francisco Domingo Carlos Andres Sebastián d'Anconia");
firstTree.addNode(25, "John Galt");
firstTree.addNode(15, "Hugh Akston");
firstTree.addNode(30, "Ragnar Danneskjöld");
firstTree.addNode(85, "Hank Reardan"); //implementing add method
BstTest2 secondTree = new BstTest2();
secondTree.addNode(50, "Francisco Domingo Carlos Andres Sebastián d'Anconia");
secondTree.addNode(25, "John Galt");
secondTree.addNode(15, "Hugh Akston");
secondTree.addNode(30, "Ragnar Danneskjöld");
secondTree.addNode(75, "Midas Mulligan");
secondTree.addNode(85, "Hank Reardan");
if(firstTree.isEqual(secondTree))
{
System.out.println("firstTree and secondTree are equal");
}
else
{
System.out.println("firstTree and secondTree are not equal");
}
isEqual and check methods for comparing the trees
public boolean isEqual(BstTest2 tree1)
{
return check(this.rootNode, tree1.rootNode);
}
public boolean check(Node node1, Node node2)
{
if((node1 == null) && (node2 == null))
{
return true;
}
else if((node1 == null) || node2 != null)
{
return false;
}
else if((node1 != null) || node2 == null)
{
return false;
}
else
{
return check(node1.leftChild, node2.leftChild) && check(node1.rightChild, node2.rightChild);
}
}
What did I do wrong in my isEqual() and check() methods that I keep getting " firstTree and secondTree are equal" when the trees are not equal?
You forget to check if the value of node1 and node2 are the same.
If they are not the same, it means these two trees are not same.
If they are the same, we keep on checking if their left and right child are the same.
public boolean check(Node node1, Node node2)
{
if((node1 == null) && (node2 == null))
{
return true;
}
// If only one node is null, it means these two trees are not the same
// These two nodes here couldn't both be null because we check this condition earlier.
if(node1 == null || node2 == null)
{
return false;
}
// Check if the value of node1 and node2 are the same
if(node1.val != node2.val)
{
return false;
}
return check(node1.leftChild, node2.leftChild) && check(node1.rightChild, node2.rightChild);
}
Related
public static boolean identical(treenode<Integer> root1,treenode<Integer> root2)
{
boolean ans;
for(int i=0;i<root1.children.size();i++)
for(int j=0;j<root2.children.size();j++)
{
boolean subans=identical(root1.children.get(i),root2.children.get(j));
ans=subans;
}
if(root1.data==root2.data)
{
ans=true;
}/* what's wrong with the code*/
else{
ans=false;
}
return ans;
}/* how can i improve it ? */
i am not able to understand why my code is not working.please tell me the solutions to fix it.
Your for loop is going through every recursive call of identical before evaluating the boolean return of those recursive calls. In other words, you're not evaluating the data of all of the children through your recursive calls. I believe with your code that you may only be evaluating the last child node of every node in the tree (going down the right-most side).
You also have a nested for loop, which is unnecessary in your case.
What I propose is this:
1) Check that the values of your current nodes are the same. If not, or if at least one is null, return false immediately.
2) Check that the sizes of the children are the same for both nodes. If not, return false.
3) Call this recursively with each child node.
This is a depth first, left-side-first search.
private boolean structurallyIdentical(Node tnode, Node onode) {
if(tnode == null && onode == null) {
return true;
}
if(tnode != null && onode != null) {
// check that the left branch is identical
boolean left = structurallyIdentical(tnode.left, onode.left);
// check that the right branch is identical
boolean right = structurallyIdentical(tnode.right, onode.right);
// only identical, if both branches match
return (left && right);
}
return false;
}
A little improvement based on #Vansh Nandwani's answer.
SBT = Same Binary Tree
public boolean SBT(BinNode root1, BinNode root2)
{
if (root1 == null && root2 == null) return true;
if (root1 != null && root1 != null) {
if (root1.value() == root2.value())//check if the values are the same
{
boolean left = SBT(root1.left(), root2.left());
boolean right = SBT(root1.right(), root2.right);
return (left && right);}
}
return false;
}
public class Solution {
/* TreeNode structure
class TreeNode<T> {
T data;
ArrayList<TreeNode<T>> children;
TreeNode(T data){
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
}*/
public static boolean checkIdentical(TreeNode<Integer> root1, TreeNode<Integer> root2){
if(root1.children.size()!=root2.children.size())
{
return false;
}
if(root1.children.size()==root2.children.size()){
if(root1.data==root2.data)
{
for(int i=0 ,j=0;i<root1.children.size()&&j<root2.children.size();i++ ,j++){
checkIdentical(root1.children.get(i),root2.children.get(j));
return true;
}
}
}
return false;
}
}
bool areIdentical(TreeNode<int> *root1, TreeNode<int> * root2)
{bool ans=false;
if(root1->children.size()!=root2->children.size())
{
ans =false;
}
if(root1->children.size()==root2->children.size()){
if(root1->data==root2->data)
{
for(int j=0;j<root1->children.size();j++){
areIdentical(root1->children[j],root2->children[j]);
ans=true;
}
}
}
return ans;
}
For general tree
Method 1:
bool areIdentical(TreeNode<int> *root1, TreeNode<int> * root2) {
if(root1 == NULL && root2 == NULL){
return true;
}
if((root1 == NULL && root2 != NULL) || (root1 != NULL && root2 == NULL)){
return false;
}
if((root1->data != root2->data)|| (root1->children.size() != root2->children.size())){
return false;
}
else if(root1->children.size() == root2->children.size()){
if(root1->data == root2->data){
for(int i=0,j=0;i<root1->children.size()&&j<root2->children.size();i++,j++){
areIdentical(root1->children[i],root2->children[j]);
return true;
}
}
}
return false;
}
//this solution may fail some testcase but
Method 2 : work perfectly fine
Method 2 :
bool areIdentical(TreeNode<int> *root1, TreeNode<int> * root2) {
if(root1 == NULL && root2 == NULL){
return true;
}
if((root1 == NULL && root2 != NULL) || (root1 != NULL && root2 == NULL)){
return false;
}
if((root1->data != root2->data)|| (root1->children.size() != root2->children.size())){
return false;
}
for(int i = 0;i < root1->children.size();++i){
TreeNode<int>* child1 = root1->children[i];
TreeNode<int>* child2 = root2->children[i];
if(!areIdentical(child1,child2)){
return false;
}
}
return true;
}
Structurally identical
public static boolean checkIdentical(TreeNode<Integer> root1, TreeNode<Integer> root2){
int size1=root1.children.size();
int size2=root2.children.size();
if(root1==null && root2==null){
return true;
}
if((root1==null && root2!=null) || (root1!=null && root2==null)){
return false;
}
if((root1.data!=root2.data)||(size1!=size2)){
return false;
}
if(size1==size2){
if(root1.data==root2.data){
for(int i =0;i<size1;i++){
for(int j=0;j<size2;j++){
TreeNode<Integer> child1=root1.children.get(i);
TreeNode<Integer> child2=root2.children.get(i);
if(!checkIdentical(child1,child2)){
return false;
}
}
}
}
}
return true;
}
Question -> Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
My Solution ->
public class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null || sum == 0){
return false;
}
List<Integer> resultSet = new ArrayList<Integer>();
Integer result = root.val;
inorder(root, result, resultSet);
return resultSet.contains(sum);
}
public void inorder(TreeNode root, Integer result, List<Integer> resultSet){
if (root.left == null && root.right == null){
resultSet.add(result);
}
if (root.left != null) {
result += Integer.valueOf(root.left.val);
inorder(root.left, result, resultSet);
}
if (root.right != null) {
result += Integer.valueOf(root.right.val);
inorder(root.right, result, resultSet);
}
}
}
Output ->
Input:
[1,-2,-3,1,3,-2,null,-1]
3
Output: true
Expected: false
I am really not sure where I am going wrong with this. I tried playing with the int and Integer type options for result , but it didn't work. Please help.
The problem I see is with result variable as once you add the value of left node to the result and are done with the left subtree then u will add the value of right child to the result, which is wrong as now it is has the sum of both left and right child value.
So essentially you are adding the values of all the nodes in the result that come before
the node root in the inorder traversal.
Can you try this:
public void inorder(TreeNode root, Integer result, List<Integer> resultSet){
if (root.left == null && root.right == null){
resultSet.add(result);
}
if (root.left != null) {
inorder(root.left, result+Integer.valueOf(root.left.val), resultSet);
}
if (root.right != null) {
inorder(root.right, result+Integer.valueOf(root.right.val), resultSet);
}
}
EDIT:1
Another simple approach to solve this problem: You don't need to create a array which contains the sum of all the root to leaf paths. You can simply keep decrementing the required sum.
Code:
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
} else {
return hasPathSumHelper(root, sum);
}
}
boolean hasPathSumHelper(TreeNode root, int sum) {
if (root.left == null && root.right == null) {//if leaf node
if (Integer.valueOf(root.val) == sum) { //if node value is equal to sum
return true;
} else {
return false;
}
}
if ((root.left != null) && (root.right != null)) {
return (hasPathSumHelper(root.left, sum - Integer.valueOf(root.val)) || hasPathSumHelper(root.right, sum - Integer.valueOf(root.val)));
}
if (root.left != null) {
return hasPathSumHelper(root.left, sum - Integer.valueOf(root.val));
} else {
return hasPathSumHelper(root.right, sum - Integer.valueOf(root.val));
}
}
I am trying to write a method that will return true if a binary tree is full (each node has 2 child nodes or none) and false otherwise. This is working some of the time but not all. Any suggestions about where I am going wrong?
public static void testNum4()
{
System.out.println("How many nodes do you want in your tree?");
int num=sc.nextInt();
//TreeNode<Integer> root = TreeUtil.createBalancedNumberTree(num); Use to test for a balanced tree
TreeNode<Integer> root = TreeUtil.createIntegerTree(num);
TreeUtil.displayTreeInWindow(root);
System.out.println(isFull(root));
TreeUtil.displayTreeInWindow (root);
}
public static boolean isFull(TreeNode<Integer> root) {
// pre: root of tree, 0 or more nodes
// post: returns true if the input tree is a full tree; false otherwise
if (root!=null) {
if ((root.getLeft() != null && root.getRight() != null) || (root.getRight() == null && root.getLeft() == null))
{
return true;
}
else if (root.getLeft()!=null)
{
isFull(root.getLeft());
}
else if (root.getRight()!=null)
{
isFull(root.getRight());
}
else
return false;
}
return false;
}
Definition: a binary tree T is full if each node is either a leaf or possesses exactly two child nodes.
public static boolean isFull(TreeNode<Integer> root)
// pre: root of tree, 0 or more nodes
// post: returns true if the input tree is a full tree; false otherwise
{
if (root!=null)
{
if(root.getRight() == null && root.getLeft() == null)
{
return true;
}
if ((root.getRight() != null && root.getLeft() != null))
{
return isFull(root.getLeft())&&isFull(root.getLeft());
}
}
return false;
}
Try to add return to each statement.
else if (root.getLeft()!=null && root.getRight()!=null)
{
return isFull(root.getLeft()) && isFull(root.getRight());
}
Also, if the root node is null, then your tree is full. So the last return should be return true;
The problem is the else if and lack of return statements. Also no need to checking for null so much, and use of a method makes it more readable.
public static boolean isFull(TreeNode<Integer> node) {
if (node == null) return false;
if (isLeaf(node)) return true;
return isFull(node.getLeft()) && isFull(node.getRight());
}
public static boolean isLeaf(TreeNode<Integer> node) {
return node.getRight() == null && node.getLeft() == null;
}
You are not fully traversing the tree. Use recursion to hit all the nodes. Check the root node. If there are no children, return true. If there are children, make sure there are two, and then check each of them recursively.
I think that the if statements should be as follows:
if (root.getRight() == null && root.getLeft() == null)
{
// The node has no children (full)
return true;
}
else if (root.getLeft() != null && root.getRight() != null)
{
// There are two children. Tree is only full if both sub trees are full
return isFull(root.getLeft()) && isFull(root.getRight());
}
else
{
// Only one child
return false;
}
All the algoritms above return true in this case (as they shouldn't):
complete binary tree
. So, hope this helps:
//-1 means "false"
public boolean full() {
int high = 0;
return ( root != null && isFull(root, high) != -1 );
}
public boolean isLeaf() {
return node.getRight() == null && node.getLeft() == null;
}
private int isFull(TreeNode<T> node, int high)
{
++high;
if (node.isLeaf())
return high;
else
{
int hLeft=0, hRight=0;
if(node.getLeft() != null)
hLeft = isFull(node.getLeft(), high);
if(node.getRight() != null)
hRight = isFull(node.getRight, high);
if ( (hLeft == hRight) && (hLeft != -1) )
return ++high;
return -1;
}
}
another easy one but I can't seem to get it. I need to write a method that compares the structures of two binary trees and returns weather they are the same or not. The data and data types are not important only the structures. Here are some examples:
Here is the code I have so far. I think it is really close.
public boolean sameStructure(OrderedSet<E> other) {
if (other.size() != size)
return false;
return sameStructureHelp(other, root, other.root);
}
private boolean sameStructureHelp(OrderedSet<E> other, TreeNode ref,
TreeNode otherRef) {
if (otherRef == null && ref != null)
return false;
if (otherRef != null && ref == null)
return false;
sameStructureHelp(other, ref.left, otherRef.left);
sameStructureHelp(other, ref.right, otherRef.right);
return true;
}
What you pasted is mostly right, only missing a critical piece: instead of just checking the left and right subtrees, you should return their and value, which would mean if the trees rooted in the current nodes satisfies the condition for being the same stucture.
Thanks #Ziyao Wei
Here is the code which solved the problem:
public boolean sameStructure(OrderedSet<E> other) {
if (other.size() != size)
return false;
return sameStructureHelp(other, root, other.root);
}
private boolean sameStructureHelp(OrderedSet<E> other, TreeNode ref,
TreeNode otherRef) {
if (otherRef == null && ref != null)
return false;
if (otherRef != null && ref == null)
return false;
if (otherRef == null && ref == null)
return true;
return sameStructureHelp(other, ref.left, otherRef.left)
&& sameStructureHelp(other, ref.right, otherRef.right);
}
I've been asked to write a recursive method to investigate whether or not there are any single children. I have get the base cases but am a bit confused about how to go about the recursive section as I will need to investigate both the right and the left subtree and return false if one of them has a single child and true if one of them has 0 children or recur.
what I have so far is:
public static boolean noSingleChildren( BinaryTreeNode t ) {
if (rightC == null || leftC == null) {
return false;
} else if (rightC == null && leftC == null) {
return true;
} else {
return............
}
}
The logic is quite simple:
If the current node only has a single child, you're done.
Otherwise, recursively ask each non-null child the same question, and combine the answers using logical "or".
Since this looks like homework, I leave the implementation to you.
public static boolean noSingleChildren( BinaryTreeNode t ) {
if (rightC == null || leftC == null) {
return false;
} else if (rightC == null && leftC == null) {
return true;
} else {
return noSingleChildren(t.getLeftBranch()) || noSingleChildren(t.getRightBranch());
}
}
Ho, I love trees questions:
public static boolean hasSingleChildren( BinaryTreeNode t ) {
if (t == null) {
return false;
} else if (t.rightC == null && t.leftC != null) {
return true;
} else if (t.rightC != null && t.leftC == null) {
return true;
} else {
return hasSingleChildren(t.rightC) || hasSingleChildren(t.leftC);
}
}