Binary tree recursion java - java

I want to write a function which returns a string of 0s and 1s to signify a path from root Node to specific node p, where 0 means go left, and 1 means go right.
__3__
/ \
4 5
/ \ /
9 2 1
2 should return "01"
public String traverse(TreeNode root, TreeNode p,String s) {
if (root == p) return s;
if (root.left != null) return traverse(root.left,p,s + "0");
if (root.right != null) return traverse(root.right,p,s+ "1");
return "-1";
}
This is my idea of recursive way but it just returns -1 when it gets to a leaf, whereas i want it to continue the recursion. As in, to find 2, it tries 3 -> 4-> 9, but does not continue 4's recursion, but stops at 9. What can I do?

You are returning a special sentinel value, "-1" when you don't find the value you're looking for on a particular branch of the tree.
But you're not checking for this value anywhere in your code - when the value you're looking for isn't on the left branch of the tree, you need to search in the right branch.
So, you need to add a check after searching the left branch of the tree that you didn't get the sentinel value as the result. If you did, you need to continue searching.
public String traverse(TreeNode root, TreeNode p, String s) {
if (root == p) {
return s;
}
if (root.left != null) {
String result = traverse(root.left, p, s + "0");
if (!"-1".equals(result)) {
return result;
}
}
if (root.right != null) {
return traverse(root.right, p, s + "1");
}
return "-1";
}

Related

Determine if 2 binary trees are similar

I am having trouble finding out if the number of nodes at each level is the same. The question and my code so far is provided below
Two binary trees are called similar sized if the number of nodes is the same at each level of the tree
Given the following:
class TreeNode {
String nodeValue;
TreeNode rightNode;
TreeNode leftNode;
TreeNode(String nodeValue, TreeNode rightNode, TreeNode leftNode) {
this.nodeValue = nodeValue;
this.rightNode = rightNode;
this.leftNode = leftNode;
}
}
The goal of this question is to write a function that will validate if two trees are similar sized.
The function should return true if this is correct and false otherwise
my code:
//implemented with java
class TreeNode {
String nodeValue;
TreeNode rightNode;
TreeNode leftNode;
TreeNode(String nodeValue, TreeNode rightNode, TreeNode leftNode) {
this.nodeValue = nodeValue;
this.rightNode = rightNode;
this.leftNode = leftNode;
}
//function to return size of node, i.e. number of children
int nodeSize() {
//if node has both left and right child node
if (this.rightNode.nodeValue != null && this.leftNode.nodeValue != null) {
return 2;
//if node has no child nodes
} else if (this.rightNode.nodeValue == null && this.leftNode.nodeValue == null) {
return 0;
//if node just has either left or right child node
} else {
return 1;
}
}
boolean similarSizedTrees(TreeNode firstTree, TreeNode secondTree) {
//if both nodes have no child nodes
if (firstTree.nodeSize() == 0 && secondTree.nodeSize() == 0) {
return true;
}
//if both nodes have at least 1 child node
if (firstTree.nodeSize() != 0 && secondTree.nodeSize() != 0) {
return ((firstTree.nodeSize() == secondTree.nodeSize()) &&
similarSizedTrees(firstTree.leftNode, secondTree.leftNode) &&
similarSizedTrees(firstTree.leftNode, secondTree.rightNode));
}
//
return false;
}
}
What I am having trouble with is my code does not account for the number of nodes at each level.
Your recursion based approach wouldn't work, because the number of nodes in the next level aren't influenced by which node each child descends from. You could modify your approach to use a simple level order traversal.
(Edit: adding #Piotr's explanation)
The basic idea is to count nodes on each level. In the example picture there is 1 node on level 1, 2 nodes on level 2 and 3 nodes on level 3 and finally 1 node on level 4. These numbers are exactly the same for both tree, even if they are not exactly the same. This algorithm is computing these counts for each level, and if discrepancy is found, it returns False. Otherwise it returns True in the end if both trees are similar. (I'm not well versed in Java, but you can easily translate the algorithm):
def similar(firstTree, secondTree):
queue1, queue2 = queue(firstTree), queue(secondTree) # create queues for traversal
# each queue stores all nodes in a given level
while queue1 and queue2:
if len(queue1)!=len(queue2): # check base condition
return False
i = 0
while i<len(queue1): # append all next level nodes for tree 1
node = queue1.pop()
if node.left:
queue1.insert(node.left)
if node.right:
queue1.insert(node.right)
i += 1
i = 0
while i<len(queue2): # append all next level nodes for tree 2
node = queue2.pop()
if node.left:
queue2.insert(node.left)
if node.right:
queue2.insert(node.right)
i += 1
if queue1 or queue2:
return False # either tree couldn't complete traversal because of different heights
return True
A couple solutions can be found here: https://www.techiedelight.com/check-if-two-binary-trees-are-identical-not-iterative-recursive/
this is the recursive function shown from the link mentioned above tailored to your code.
boolean similarSizedTrees(TreeNode x, TreeNode y) {
// bottom of tree reached
if (x == null && y == null) {
return true;
}
// both trees are non-empty and the value of their root node matches,
// recur for their left and right subtree
return (x != null && y != null) && (x.key == y.key) &&
similarSizedTrees(x.left, y.left) &&
similarSizedTrees(x.right, y.right);
}
EDIT: You could also keep count of the nodes at each level using two global int variables, one for each tree, as you traverse the tree increment each variable, then compare them together before continuing down to the next level.
Here is a solution using recursion:
int find_height(TreeNode t){
return (t == null)? 0 : 1 + Math.max(find_height(t.leftNode), find_height(t.rightNode));
}
boolean is_similar_tree(TreeNode l, TreeNode r){
int l_height = find_height(l);
int r_height = find_height(r);
if(l_height != r_height)
return false;
int[] l_height_sums = new int[l_height];
int[] r_height_sums = new int[r_height];
is_similar_tree_helper(l, l_height_sums, l_height);
is_similar_tree_helper(r, r_height_sums, r_height);
return Arrays.equals(l_height_sums, r_height_sums);
}
void is_similar_tree_helper(TreeNode t, int[] table, int height){
if(t == null || height == 0)
return;
table[height - 1]++;
is_similar_tree_helper(t.leftNode, table, height - 1);
is_similar_tree_helper(t.rightNode, table, height - 1);
}
The idea is to count the number of nodes in each level, then check if the total number of levels of two trees are the same or not. If it is not the same then return false otherwise check each level count and compare the value. If two values are equal then return true otherwise false.
class TreeNode {
String nodeValue;
TreeNode rightNode;
TreeNode leftNode;
TreeNode(String nodeValue, TreeNode rightNode, TreeNode leftNode) {
this.nodeValue = nodeValue;
this.rightNode = rightNode;
this.leftNode = leftNode;
}
public void countLevelNode(TreeNode root, int level, int[] sum) {
if(root == null) return;
sum[level]++;
countLevelNode(root.leftNode, level + 1, sum);
countLevelNode(root.rightNode, level + 1, sum);
}
boolean similarSizedTrees(TreeNode firstTree, TreeNode secondTree) {
int[] countFirstTreeNode = new int[1000];
int[] countSecondTreeNode = new int[1000];
int totalLevelofFirstTree = 0;
int totalLevelofSecondTree = 0;
countLevelNode(firstTree, totalLevelofFirstTree, countFirstTreeNode);
countLevelNode(secondTree, totalLevelofSecondTree, countSecondTreeNode);
if(totalLevelofFirstTree != totalLevelofSecondTree){
return false;
}
else{
for(int i = 0; i < totalLevelofFirstTree; i++){
if(countFirstTreeNode[i] != countSecondTreeNode[i]){
return false;
}
}
return true;
}
}
}

Similiar functions to traverse a binary tree

I have got a binary tree
public class Node
{
int value;
Node left;
Node right;
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public String getValue() {
return value;
}
}
And in main I have got a function to traverse it.
For tree
5
/ \
3 7
/ \
1 2
First one creates a queue of nodes with breadth first traversal(5,3,7,1,2).
Second one returns value of a node for eg. 7 for number 2 or 2 for number 4.
private void queueOfTreaversed() {
LinkedList<Node> queue = new LinkedList<Node>();
if (root != null)
queue.add(root);
while (!queue.isEmpty()) {
Node temp = queue.removeFirst();
if (temp.getLeft() != null && temp.getRight() != null) {
traversed.add(temp); //there is a difference
queue.add(temp.getLeft());
queue.add(temp.getRight());
}
}
}
public int getValue(int n) {
LinkedList<Node> queue = new LinkedList<Node>();
if (root != null)
queue.add(root);
while (!queue.isEmpty() && n>0) {
Node temp = queue.removeFirst();
if (temp.getLeft() != null && temp.getRight() != null) {
queue.add(temp.getLeft());
queue.add(temp.getRight());
}
}
return queue.peekFirst().getValue(); //there is a difference
}
And I have got duplication of code that I do not how to get rid off.
I use traversed in meantime and pop elements from this queue so elements will not be in this order and traversed cannot be used. Could anyone give any hint?
Once you have got the traversed nodes in traversed, your getValue(int n) function can actually index into traversed to get the value you want. In your getValue(int n) function, just use code like this:
if (n < traversed.size()) {
return traversed.get(n).getValue();
}
throw new Exception("Element not existed");
To be able to use traversed, just return it in your queueOfTreaversed function.

binary search tree findNode method always returns root

I have a Binary Search Tree of integers including 1,2,...,9. My traversal methods work, I know that the nodes are there and in the correct order.
I made two methods for searching, one that finds and returns the node, and one that calls that method and prints whether or not the node exists depending on what it returns (null means it doesn't exist).
The findNode(int, BSTNode), however keeps returning the root. When I compare it to example code online, it seems to be correct.
here are the two methods, I call searchPrint(int) from the main method on 7,5,6,1,12,15 (Note that 12 & 15 do not exist in the tree):
//this method calls findNode(int,BSTNode) and prints a message if the value is found
// in the tree
public void searchPrint(int value)
{
System.out.print(value);
if (findNode(value, root) == null)
{
System.out.println(" does not exist in the tree.");
} else
{
System.out.println(" exists in the tree.");
}
}//end searchPrint(int) ----------------------------------------------------
//this method recursively looks for the node that contains 'value' and
//returns that node if it is found. Returns null if no nodes contain
//the value.
private BSTNode findNode(int value, BSTNode current)
{
if(current != null)
{
if (value == current.getValue())
{
System.out.print(" **Test* entering "
+ "if(value = current.value loop...** ");
return current;
} else
{
if (value < current.getValue())
{
findNode(value,current.getLeft());
} else
{
findNode(value,current.getRight());
}
}
} else
{
return null;
}
return current;
}//end findNode(int,BSTNode) -----------------------------------------------
here is the output:
Traversals:
in-order
1
2
3
4
5
6
7
8
9
pre-order
6
2
1
4
3
5
7
9
8
post-order
1
3
5
4
2
8
9
7
6
7 **Test* entering if(value = current.value loop...** exists in the tree.
5 **Test* entering if(value = current.value loop...** exists in the tree.
6 **Test* entering if(value = current.value loop...** exists in the tree.
1 **Test* entering if(value = current.value loop...** exists in the tree.
12 exists in the tree.
15 exists in the tree.
Iv'e written down on paper what happens when I search for a value and it makes no sense that it returns the root. What am I doing wrong?
Your recursive call findNode(value,current.getLeft()); or findNode(value,current.getRight()); will return actual result. You are just keeping that result without any use.
Instead of that,
use
return findNode(value,current.getLeft());
and
return findNode(value,current.getRight());
You are missing return in the recursive call to findNode(), so it always reach the return at the end of the method
Change to:
private BSTNode findNode(int value, BSTNode current)
{
if(current != null)
{
if (value == current.getValue())
{
System.out.print(" **Test* entering "
+ "if(value = current.value loop...** ");
return current;
} else
{
if (value < current.getValue())
{
return findNode(value,current.getLeft());
} else
{
return findNode(value,current.getRight());
}
}
} else
{
return null;
}
return current;
}

Binary Search Tree Remove Method

I am making a binary search tree which is sorted by String key. Each node consists of an unordered linked list of information that is associated to a key. The tree is inorder (alphabetical).
I have completed most of the program, but having trouble with the remove method.
Essentially it has to be recursive. The method has to remove a node that has the given key, such that if "Architecture" was the String given, I must traverse through the tree and remove the corresponding node with "Architecture" as its key.
I am having trouble because I have to remove a String. Other assignments have used integers where I have to remove the highest or lowest value. However, I am not removing a node with the highest or lowest String value, but a node that equals to a specified String.
All I'm asking is how to go about this method. You don't have to provide any actual code if you choose not to, but some pointers or advise would be nice.
Thank you.
//My attempt:
//Removes node with corresponding k
public void remove(String k) {
rootNode = remove(rootNode, k);
}
//Recursive method:
private KeyNode remove(KeyNode x, String k) {
if (x == null) {
return x;
}
//int comparison with compareTo
//if less than 0, left node = remove(left node, k)
//if greater than 0, right node = remove(right node, k)
//if left node and right node are both null, return null
//if left node is null, return left node
//if right node is null, return right node
//return
}
you could do something like this
public rootNode remove (String k, rootNode n) {
if (n == null)
return null;
if (k.compareTo(n.key)<0)
remove (k, n.leftChild);
else if (k.compareTo(n.key)>0)
remove (k, n.rightChild);
else {
if (n.leftChild != null && n.rightChild != null) {
/* n has two children, find max from left then
* switch it with n and remove n */
}
else if(n.leftChild != null) {
/* n has a left child only then left child replaces n
* and n is deleted */
}
else if(n.rightChild != null) {
/* n has a right child only then right child replaces n
* and n is deleted*/
}
else {
n = null;
}
}
}

Recursively searching binary tree issue

I have written the below code for recursively searching binary tree .
Even though my system.out statement is getting executed , the return statement is not returning out of entire recursion and thus this method not returning true.
Can anyone suggest how can I return out of entire recursion.?
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
if (root != null)
{
int rootVal = root.getData();
BinaryTreeNode left = root.getLeft();
BinaryTreeNode right = root.getRight();
if (left != null)
{
isElementinTree(num,left);
}
if (right != null)
{
isElementinTree(num,right);
}
if (num == rootVal)
{
System.out.println("------ MATCH -----");
return true;
}
}
return false;
}
This is the problem:
if (left != null)
{
isElementinTree(num,left);
}
if (right != null)
{
isElementinTree(num,right);
}
You're calling the method in those cases - but ignoring the result. I suspect you just want to change each of those to return immediately if it's found:
if (left != null && isElementinTree(num, left))
{
return true;
}
if (right != null && isElementinTree(num, right))
{
return true;
}
Or to make the whole thing more declarative, you can do it more simply:
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
return root != null && (root.getData() == num ||
isElementInTree(num, root.getLeft()) ||
isElementInTree(num, root.getRight()));
}
It's fine to call isElementInTree with a null second argument, as you're already protecting against that with the first part.
What is wrong with a simple solution like this:
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
return root != null && //The tree is non-null
(num == root.getData() || //We have num in this node OR
isElementInTree(num, root.getLeft()) || //We have num in left subtree OR
isElementInTree(num, root.getRight()) ); //We have num in right subtree
}
You need to check if the value is in one of the branches, and save that result.
Initialize a variable boolean found = false;.
When you do the recursive call, you need to do something like:
found = isElementinTree(num,left)
same thing for the right side.
At the end, instead of returning false, check if the value was found on a branch, simply return found;
Also, first check if the number you are looking for isn't on the Node itself, instead of searching each branch first. Simply switch the order of the if's.
If you do find the element you're looking for in the left or right subtrees you need to return this fact back up to the caller:
if (left != null)
{
if(isElementinTree(num,left)) return true;
}
if (right != null)
{
if(isElementinTree(num,right)) return true;
}
Only if you find it in none of the left tree, right tree and current node do you eventually fall through to the final return false.
Recursion solution:
boolean isElementinTree (int num, BinaryTreeNode root)
{
if(root == null)
return false;
if(root.value == num)
return true;
boolean n1 = isElementinTree(num,root.getLeft());
boolean n2 = isElementinTree(num,root.getRight());
return n1 ? n1 : n2;
}

Categories