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);
}
}
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;
}
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;
}
}
I can't seem to think of a way to solve this. At least not an elegant way. The function should determine if a given tree is a binary search tree. It seems to work (no duplicates are allowed now though).
This is where the function starts:
isBinarySearchTree(root)
Function:
public static boolean isBinarySearchTree(Node node) {
if (node.leftchild != null) {
if (node.leftchild.key < node.key)
isBinarySearchTree(node.leftchild);
else {
System.out.println("false: " + node + " -> " + node.leftchild);
return false;
}
}
if (node.rightchild != null) {
if (node.rightchild.key > node.key)
isBinarySearchTree(node.rightchild);
else {
System.out.println("false: " + node + " -> " + node.rightchild);
return false;
}
}
return true;
}
Obviously there is something wrong with the way I want to return. This would work if all the boolean return values would be in a logical && chain. The return value should only be true if all return values are true.
How would I have to rewrite the function to work like that? Or is it even possible?
This should work, I guess :
public static boolean isBinarySearchTree(Node node, int key) {
if (node.leftchild != null && node.leftchild.key < key || node.rightchild != null && node.rightchild.key > key) {
return false;
} else {
return (node.leftchild != null ? isBinarySearchTree(node.leftchild, node.leftchild.key) : true) && (node.rightchild != null ? isBinarySearchTree(node.rightchild, node.rightchild.key) : true);
}
}
You need to logically AND the results of your test on the left and test on the right, and return the result, something like return (leftnode == null || (leftnode.key < key && isBinarySearchTree(leftnode))) && (rightnode == null || (key < rightnode.key && isBinarySearchTree(rightnode)));. It might be clearer to break that into several lines, though.
public static boolean isBinarySearchTree(Node node) {
if(node==null)
return false;
if(node.left!=null &&node.key <node.left||node.right!=null &&node.key >node.right)
return false;
if((getMax(node.left)>getMin(node.right)) //Left subtree should not have a value which larger than min in right subtree
return false;
//check recurisvely left and right subtrees
if(!(isBinarySearchTree(node.left)&&isBinarySearchTree(node.right)))
return false;
return true;
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);
}