To print a binary tree path with a leaf node value. When it backtracks, it should remove the '3' from the stack. How to modify the code to achieve? I can't find a place to pop the value from the stack.
// should print out "5 8 10", but it prints "5 3 8 10"
printPathWithStack(root, 5);
10
/ \
8 2
/ \ /
3 5 4
void printPathWithStack(Node root, int key)
{
Stack<Node> path = new Stack<Node>();
printPathWithStackHelper(root, key, path);
}
void printPathWithStackHelper(Node root, int key, Stack<Node> path)
{
if (root == null) {
return;
}
path.push(root);
if (root.data == key && root.left == null && root.right == null) {
while (!path.isEmpty()) {
System.out.print(path.pop().data + " ");
}
} else if (root.left == null && root.right == null){
path.pop();
}
printPathWithStackHelper(root.left, key, path);
printPathWithStackHelper(root.right, key, path);
}
Well, it's a bit strange to use the stack this way.
But for what it's worth, when backtracking you should simply discard all items where item.left or item.right is not equal the last retrieved item. This will give you the path to the root.
You can defer pushing into Stack until making recursive calls to left and right child.
if (root.data == key && root.left == null && root.right == null)
{
path.push(root);
while (!path.isEmpty())
{
System.out.print(path.pop().data + " ");
}
return;
}
else if (root.left == null && root.right == null)
{
return;
}
path.push(root);
printPathWithStackHelper(root.left, key, path);
printPathWithStackHelper(root.right, key, path);
Hope it addresses your problem!
P.S. Not tested the code fragment for general cases, hope you will do the required :)
Related
I am trying to write binary search insert method but it gives the wrong answer. I couldn't find what is the reason. Here's my code:
public static Node insert(Node root,int data) {
Node insertedNode = new Node(data);
if(root == null){
root=insertedNode;
}
else {
Node node = root;
Node insertedNode = new Node(data);
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
if (data > root.data) {
root.left = insertedNode;
}
else {
root.right=insertedNode;
}
}
}
The problem is very easy to detect. Look at your while:
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
It will only seek to deeper levels if both left and right of root exists. So, let's suppose you try to add 2, 3, 4. You insert 2, which will become your root. Then, you try to add 3. Your while detects that it's not true that both of left and right of root are not null. So, it will add 3 to the right. So far, so good:
2
\
3
Now, you try to add 4. Your while checks whether root.left and root.right are not null. It's false, so it will be the right of the root, resulting in
2
\
4
instead of
2
\
3
\
4
Let's fix your while:
while((root != null) && (((root.data < data) && (root.left != null)) || ((root.data > data) && (root.right != null)))){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
There's a practice problem that I've been working on that's been confusing me.
Define a function treeLevelOrder which satisfies the following claim:
If Q is a binary search tree of integers, then treeLevelOrder(Q) is the String representation of the contents of Q according to their level in the tree.
We get this tree as an example
9
/ \
5 16
/ \ / \
1 7 12 19
The value of the expression treeLevelOrder(Q) in this case would be
"[9,5,16,1,7,12,19]".
I've seen similar problems, but they don't follow the same format that I'm looking for, wanting to print by level order or as ordered tuples. Here's some sample code I've been working on:
private String treeLevelOrder(Node Q)
{
if (Q.left == null && Q.right == null)
return "[" + Q.datum + "]";
else if (Q.left == null && Q.right != null)
return "[" + Q.datum + ", "+Q.right.datum+"]" + treeLevelOrder(Q.right);
else if (Q.left !=null && Q.right == null)
return"[" + Q.datum + ", "+Q.left.datum+", *]"+ treeLevelOrder(T.left);
else
return "[" + Q.datum + ", "+Q.left.datum+", "+Q.right.datum+"]" +
treeLevelOrder(Q.left) + treeLevelOrder(Q.right);
}
Any assistance would be helpful.
EDIT: Okay, so I've been experimenting with the level order example at Geeks for Geeks, thank you curlyBraces, that would be closer to what I'm looking for, though I can't figure out to make it return a string. Here's the code they use:
/* function to print level order traversal of tree*/
void printLevelOrder()
{
int h = height(root);
int i;
for (i=1; i<=h; i++)
printGivenLevel(root, i);
}
/* Compute the "height" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int height(Node root)
{
if (root == null)
return 0;
else
{
/* compute height of each subtree */
int lheight = height(root.left);
int rheight = height(root.right);
/* use the larger one */
if (lheight > rheight)
return(lheight+1);
else return(rheight+1);
}
}
/* Print nodes at the given level */
void printGivenLevel (Node root ,int level)
{
if (root == null)
return;
if (level == 1)
System.out.print(root.data + ", ");
else if (level > 1)
{
printGivenLevel(root.left, level-1);
printGivenLevel(root.right, level-1);
}
}
Any ideas?
Here's an implementation using while loop and two queues to keep track of all the nodes:
public String treeLevelOrder(Node root) {
StringBuilder result = new StringBuilder("");
Queue<Node> current = new LinkedList<>();
Queue<Node> other = new LinkedList<>();
if(root != null)
current.add(root);
while(!current.isEmpty()) {
while(!current.isEmpty()) {
Node node = current.remove();
result.append(",");
result.append(node.datum);
// adding children to the other queue
if(node.left != null)
other.add(node.left);
if(node.right != null)
other.add(node.right);
}
// swapping the queues
Queue<Node> temp = current;
current = other;
other = temp;
}
// building final string
if(result.length() == 0)
result.append("[");
else
result.setCharAt(0,'[');
result.append("]");
return result.toString();
}
I'm writing a method for a homework problem on binary trees.
Objective:
Given a binary tree, check if the tree satisfies the property that for each node, the sum of the values of its left and right children are equal to the node's value. If a node has only one child, then the node should have the same value as that child. Leaf nodes automatically satisfy the property.
I am getting an error that my code is not correct for all cases. For example if I have a tree
15
/ \
5 10
I am returning false when it should be true.
Here is my method so far, what am I doing wrong?
boolean BTchecksum(BinNode root) {
if (root == null || root.left() == null && root.right() == null) {return true;}
BinNode leftNode = root.left();
BinNode rightNode = root.right();
int sum = (int)(leftNode.element()) + (int)(leftNode.element());
int value = (int)(root.element());
return (sum == value) && BTchecksum(root.left()) && BTchecksum(root.right());
}
You wrote sum as:
leftNode.element()) + (int)(leftNode.element)));
Should be this:
leftNode.element()) + (int)(rightNode.element)));
Right now, you're probably getting null pointer exceptions because you're referencing children that may be null. This may not be the most efficient solution, but it takes care of all the cases.
public boolean BTchecksum(BinNode root) {
if (root == null || root.right()==null && root.left()==null) {
return true;
}
if (root.right() == null) {
return (root.left().value() == root.value())
&& BTchecksum(root.left());
} else if (root.left() == null) {
return (root.right().value() == root.value())
&& BTchecksum(root.right());
} else {
return (root.value() == root.left().value() + root.right().value())
&& BTchecksum(root.left()) && BTchecksum(root.right());
}
Revision (no NullPinterException)
public boolean BTchecksum(BinNode root)
{
if (root == null || root.left() == null && root.right() == null) {return true;}
int sum = 0;
if (root.left() != null){sum = sum + root.left().value();}
if (root.right() != null){sum = sum + root.right().value();}
return (sum == root.value()) && BTchecksum(root.left()) && BTchecksum(root.right());
}
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'm confused on why my removal method of leaves in a BST is not working. If I assign 0 to the data, its reflected in the tree, but when I assign null to the node, it's still able to be referenced in the BST traversal.
public void removeLeaves(){
removeLeaves(getRoot());
}
private void removeLeaves(IntTreeNode node) {
if (node == null)
return;
else if( node.left == null && node.right == null){
node.data = 0; //im finding the leave nodes correctly
node = null; //but its not removing them
}
else {
removeLeaves(node.left);
removeLeaves(node.right);
}
}
overallRoot
____[7]____
/ \
[3] [9]
/ \ / \
[0] [0] [0] [8]
\
[0]
Could somebody explain why this is not working as intended?
In your example tree , consider 9
9.left => null
9.right => address of 8
when you assign node.data = 0; , node has address of 8 so 0 will be reflected in the tree.
But when you do node =null, you are just changing the variable node. you are not doing any operation on address of 8.
I think what you are hoping to happen is by doing node = null is:
address of 8 = null
which is actually not possible, because you are just changing the variable node.
Say address of 8 is 0XABCD, so node = 0XABCD.
when you do node.data=0 as node has address 0XABCD, 0XABCD.data will be changed to 0. but when you do node = null, you are just assigning a new value to a variable node, you are not doing any operation on the original address 0XABCD.
What you actually have to do is
if(node.left!= null && node.left.left == null && node.left.right ==null)
node.left =null
if(node.right!= null && node.right.left == null && node.right.right ==null)
node.right =null
UPDATE
What you are trying to do is something like this:
Foo foo = new Foo();
Foo anotherFoo = foo;
anotherFoo.value = something; // both foo.value and anotherFoo.value will be changed to "something", because of the reference.
anotherFoo = null;
// here you are expecting foo also to be null which is not correct.
public void removeLeaves () {
if (getRoot() != null)
removeLeaves (getRoot());
}
private IntTreeNode removeLeaves (IntTreeNode node) {
if (getRoot().left == null && getRoot().right == null) {
setRoot(null);
} else {
if (node.left != null) {
if (node.left.left == null && node.left.right == null)
node.left = null;
else
removeLeaves(node.left);
}
if (node.right != null) {
if (node.right.right == null && node.right.left == null)
node.right = null;
else
removeLeaves(node.right);
}
}
return node;
}