I am working on a leetcode problem where I am asked to check whether or not a Binary Search Tree is valid. So far, my solution only passes 58 out 75 test cases. Any pointers on where I went wrong and how to fix it?
Here is the question:
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Input: [2,1,3]
Output: true
Example 2:
5
/ \
1 4
/ \
3 6
Input: [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
Here is my Solution:
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidHelper(root);
}
public boolean isValidHelper(TreeNode root)
{
if(root == null)
return true;
isValidHelper(root.left);
if(root.left != null && !(root.left.val < root.val) || root.right != null && !(root.right.val > root.val))
return false;
isValidHelper(root.right);
return true;
}
}
Your program fails in cases like this:
5
3 7
1 6
because you only compare the value at the root of the subtrees.
I don't give a fix on purpose. You will learn more finding that out yourself.
Related
I've been trying to get the height of the root of 2 trees (same root). I just started working with trees and this way of traversing them without left or right references is causing me some difficulty.
I used the recursion to get to the leaf nodes then I tried to calculate the height via getParent() and a counter.
public int height(){
//code is a little messy but the first number is the height of the root
System.out.print("Height: ");
return height(root);
}
private int height(TNode tn){
if (tn == null) return 0;
int counter = 0;
//recursive call to get to the leaf nodes
for (TNode cn: tn.getChildren()){
height(cn);
}//while at the leaf nodes, count the parent nodes of the leaf nodes
while(tn.getParent() != null){ //if there's a parent
tn = tn.getParent(); //tn becomes its parent
counter+=1;
if(tn.getParent() == null && tn == root){
counter+=1;
}
}
System.out.print(counter + " ");
return counter;
}
The heights of the 2 trees are 4 and 2.
The codes yields
Height: 4 4 4 3 3 4 4 4 3 2 3 3 3 2 2 0
Height: 2 2 2 0
I've tried using stacks and arrays to isolate the 4 and 2 at the beginning but to no avail. Maybe the issue is obvious but maybe my understanding of tree traversal in this manner is a little lacking. Any suggestions would be appreciated.
REFERENCE I am copy pasting the problem and the solution that works in C, I am not able to get this working in Java. I understand primarily it is because in Java parameters are passed by value and that is causing problem to maintain state of "old_value". But I even tried changing it to a custom MyInt with set and get, still not able to get this working. So, probably I am missing something else too here. Kindly suggest.
Given a Binary Tree where each node has positive and negative values.
Convert this to a tree where each node contains the sum of the left
and right sub trees in the original tree. The values of leaf nodes are
changed to 0.
For example, the following tree
10
/ \
-2 6
/ \ / \
8 -4 7 5
should be changed to
20(4-2+12+6)
/ \
4(8-4) 12(7+5)
/ \ / \
0 0 0 0
Code:
int toSumTree(struct node *node)
{
// Base case
if(node == NULL)
return 0;
// Store the old value
int old_val = node->data;
// Recursively call for left and right subtrees and store the sum as
// new value of this node
node->data = toSumTree(node->left) + toSumTree(node->right);
// Return the sum of values of nodes in left and right subtrees and
// old_value of this node
return node->data + old_val;
}
Java Code:
public static int sumTree(Node node){
if(node == null)
return 0;
MyInt old_value = new MyInt(node.data);
node.data = sumTree(node.left) + sumTree(node.right);
return node.data + old_value.getData();
}
I was running wrong tests. Same code logic will work in Java as well as rightly pointed out in comments that pass by value does not make a difference because value is getting returned. The following is the working Java Code:
public static int sumTree(TreeNode node){
if(node == null)
return 0;
int old_value = node.value;
node.value = sumTree(node.left) + sumTree(node.right);
return node.value + old_value;
}
The method is supposed to take in two parameters one for depth and one for the integer value of the root of the tree. For Example: for any given N, returns the root reference of a full binary search tree of depth N such that the nodes store the integers 1, 2, …, 2 N+1 – 1. I'm struggling to get this right. Here is what I have:
public static BinaryNode BSTFactory(int top,int depth) {
BinaryNode root=new BinaryNode(null,null,top);
BinaryNode leftChild,rightChild;
if(depth==0){
return root;
}
if(depth==1){
//create 2 children left and right
leftChild=new BinaryNode(null,null,top-1);
rightChild=new BinaryNode(null,null,top+1);
root=new BinaryNode(rightChild,leftChild,top);
return root;
}
if(depth>1){
leftChild=BSTFactory(top-1,depth-1);
rightChild=BSTFactory(top+1,depth-1);
root=new BinaryNode(rightChild,leftChild,top);
return root;
}
return root;
}
First of all, the two parameters of your method depend on each other. For example, BSTFactory(1,3) can't be a full binary tree with a minimal node of 1, since if the root already contains the minimal node, the left sub-tree must be empty (unless you allow negative values in your tree, which is not clear from your question, since you seem to want the tree to store integers starting from 1).
Therefore, I would suggest a wrapper method that would accept only the depth, and calculate the matching root node. We'll see how the two parameters are related later.
Now let's look at some small full binary trees to figure out the recursion :
Depth 0
1
Depth 1
2
1 3
Depth 2
4
2 6
1 3 5 7
Depth 3
8
4 12
2 6 10 14
1 3 5 7 9 11 13 15
What can we learn from these examples?
If we are creating a full binary search tree of depth n :
The root would be 2^n
The left sub-tree will be rooted at root - 2^(n-1)
The right sub-tree will be rooted at root + 2^(n-1)
Therefore, the recusion should be :
public static BinaryNode BSTFactory(int root, int depth)
{
BinaryNode leftChild,rightChild;
if (depth==0){
return new BinaryNode(null,null,root);
} else {
leftChild=BSTFactory(root-Math.pow(2,depth-1),depth-1);
rightChild=BSTFactory(root+Math.pow(2,depth-1),depth-1);
return new BinaryNode(rightChild,leftChild,root);
}
}
Note that in order for this to work (i.e. that your minimal node would be 1), you must call the method with a root and depth such that root=2^depth. To ensure that, lets define a wrapper method :
public static BinaryNode BSTFactory(int depth)
{
return BSTFactory (Math.pow(2^depth),depth);
}
If you call the two parameter method with arbitrary root and depth, you can get binary trees such as :
BSTFactory (6,1)
6
5 7
BSTFactory (1,2)
1
-1 3
-2 0 2 4
There are still full binary trees, but their minimal value is not 1.
I have been trying to get this to work but while it works for majority of the input sometimes it gives the wrong output. I have spent some time debugging the code and it seems the problem is when i get a Node that is smaller than the root but bigger than the left node under the root.
How can I traverse the right sub-tree and still return the right key if no node in the right sub-tree is the floor node for that key?
Recall that if you do anything recursively, it can be transformed* into iteration.
Let's consider taking the floor of a well-formed BST, which should simply be the smallest element which is less than or equal to your key in the tree. All we have to do is traverse the tree to get it.
Let's implement it recursively so we can tease out a few important corollaries between iteration and recursion.
// Assuming non-null root node with method declaration
private Node floor(Node root, Key key, Node lowestNode) {
if(key.compareTo(root.getKey()) <= 0) {
if(root.getLeft() != null) {
return floor(root.getLeft(), key, lowestNode);
} else {
return root.compareTo(lowestNode) < 0 ? root : lowestNode;
}
} else {
if(root.getRight() != null) {
lowestRightNode.add(root);
return floor(root.getRight(), key, lowestNode);
} else {
return lowestNode;
}
}
Let's walk through the conditions for success.
If we compare a node to be less than or equal to our key value:
If we have a left child, there's something smaller. Traverse down the left half of the tree.
Otherwise, we're at the floor - which means we're at the node whose value is less than or equal to our key. Return it.
Otherwise (our node has a value greater than our key):
If we have a right child, there's a chance that our work isn't done yet (something's smaller). We'd like to keep it around since we could step off of the tree, so let's store it, then traverse down the right half of the tree.
Otherwise, we've fallen off of the tree. Return the smallest element we've kept track of.
An example may look something like this:
9
/ \
3 14
/ \
1 2
With a key of 12:
Compare with 9. We're larger. Store 9 in our lowest node variable, recurse right.
Compare with 14. We're smaller, but we don't have a left child. We compare the value 14 to 9 and 9 is smaller, so we return the node with 9.
If we want to convert this into iteration, then think about your starting point, your conditional check, and your incrementation steps.
Starting point: A non-null node
Conditional check:
key.compareTo(root.getKey()) <= 0
root.getLeft() != null
continue
root.compareTo(lowestRightNode) < 0 ? root : lowestRightNode
terminal
else
root.getRight() != null
store temp value and continue
return lowestRightNode
terminal
Pay close attention to your continuation conditions, and what other work you'd have to do to keep track of the lowest node you've seen so far (only for the right-hand side, that is).
*: Some recursive operations are more painful to convert than others, of course.
I have to create an arithmetic evaluator in Java. To do this I have to parse an algebric expression in binary tree and then calculate and return the result. So for the first step how can I parse an expression in a binary tree? I know the theory but my prob is how to do it in Java. I read the following post
create recursive binary tree
But I'm missing the basic trick or method. I know how to create a node (I have a class with methods like returnNodeValue, isLeaf, isDoubleNode, isSingleNode etc) but I think I'll need a method to insert a node in a binary tree to acheive what I want. Any ideas?
Tree construction for prefix expressions
def insert
Insert each token in the expression from left to right:
(0) If the tree is empty, the first token in the expression (must
be an operator) becomes the root
(1) Else if the last inserted token is an
operator, then insert the token as the left child of the last inserted
node.
(2) Else if the last inserted token is an operand, backtrack up the
tree starting from the last inserted node and find the first node with a NULL
right child, insert the token there. **Note**: don't insert into the last inserted
node.
end def
Let's do an example: + 2 + 1 1
Apply (0).
+
Apply (1).
+
/
2
Apply (2).
+
/ \
2 +
Apply (1).
+
/ \
2 +
/
1
Finally, apply (2).
+
/ \
2 +
/ \
1 1
This algorithm has been tested against - * / 15 - 7 + 1 1 3 + 2 + 1 1
So the Tree.insert implementation is those three rules.
insert(rootNode, token)
//create new node with token
if (isLastTokenOperator)//case 1
//insert into last inserted's left child
else { //case 2
//backtrack: get node with NULL right child
//insert
}
//maintain state
lastInsertedNode = ?, isLastTokenOperator = ?
Evaluating the tree is a little funny, because you have to start from the bottom-right of the tree. Perform a reverse post-order traversal. Visit the right child first.
evalPostorder(node)
if (node == null) then return 0
int rightVal = evalPostorder(node.right)
int leftVal = evalPostorder(node.left)
if(isOperator(node.value))
return rightVal <operator> leftVal
else
return node.value
Given the simplicity of constructing a tree from a prefix expression, I'd suggest using the standard stack algorithm to convert from infix to prefix. In practice you'd use a stack algorithm to evaluate an infix expression.
I think you might be a bit confused about what you are supposed to be doing:
... but I think I'll need a method to insert a node in a binary tree ...
The binary tree you are talking about is actually a parse tree, and it is not strictly a binary tree (since not all tree nodes are binary). (Besides "binary tree" has connotations of a binary search tree, and that's not what you need here at all.)
One you have figured out to parse the expression, the construction of the parse tree is pretty straight-forward. For instance:
Tree parseExpression() {
// ....
// binary expression case:
Tree left = parseExpression();
// parse operator
Tree right = parseExpression();
// lookahead to next operator
if (...) {
} else {
return new BinaryNode(operator, left, right);
}
// ...
}
Note: this is not working code ... it is a hint to help you do your homework.