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;
}
}
Related
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);
}
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 have a binary search tree. I know how to search using the search property. But my task is to search the tree without using search property.(Say, search in binary tree) This is how I have to search.
1. If you find the value in the current node return it.
2. else search in right. If not found in right, then search in left
3. If not found in the whole tree return null.
This is what i tried.
public Node search(int val)
{
Node target = this;
if(target.getVal() == val)
return this;
else if(target.getRight() == null && target.getLeft() == null)
return null;
if(target.getRight() != null)
{
return target.getRight().search(id);
}
if(target.getLeft() != null)
{
return target.getLeft().search(id);
}
return null;
}
Problem with my code is, if right child exists and val is not found in right I'm getting null value. (Not searching in left). How to resolve this?
public Node search(int val)
{
Node target = this;
if(target.getVal() == val)
return this;
else if(target.getRight() == null && target.getLeft() == null)
return null;
if(target.getRight() != null)
{
return target.getRight().search(id); //here lies the problem
}
if(target.getLeft() != null)
{
return target.getLeft().search(id);
}
return null;
}
The problem in your code is that you are returning the result of search in right subtree of the node being searched.
Here's the updated code
public Node search(int val)
{
Node target = null;
if(this.getVal() == val)
{
return this;
}
else if(this.getRight() == null && this.getLeft() == null)
return target;
if(this.getRight() != null)
{
target = this.getRight().search(id);
}
if(target==null && this.getLeft() != null)
{
target = this.getLeft().search(id);
}
return target;
}
This is untested code, but I'd change your logic a bit:
public Node search(int val)
{
if(this.getVal() == val)
return this;
if (this.getRight() != null) {
Node right = this.getRight().search(id);
if (right != null)
return right;
}
if (this.getLeft() != null) {
Node left = this.getLeft().search(id);
if (left != null)
return left;
}
return null;
}
In your version you are returning a solution with the sole requirement that the node on the right or left is not null. You have to return a solution only if a solution is found.
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);
}
}