Trying to determine if a tree is a valid binary search tree - algorithm

The code below passes all test cases where we try to determine if a tree is a valid BST.
public static boolean validateBst(BST tree) {
return isValid(tree, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
public static boolean isValid(BST tree, int min, int max) {
if (tree == null) {
return true;
}
if (tree.value < min || tree.value >= max) {
return false;
}
return isValid(tree.left, min, tree.value) && isValid(tree.right, tree.value, max);
}
The code above checks if a tree is a valid BST. The logic is simple, if a tree is null then it is a BST. If the value of the tree is less than the min and greater than the max we return false as it is not a valid BST condition.
The issue I have is when i change the following line:
if (tree.value < min || tree.value >= max) {
return false;
}
To the following
if (tree.value > min && tree.value < max) {
return true
}
The code does not pass all the test cases. This is confusing to me because I feel like both statements are saying the same thing.
The first if statement is saying if the value of the tree/node is less than the min or more than the max then you are not a valid BST and the second statement is saying if your value is within the range of min and max you are a valid bst.
So please help me understand why when i change that line my code does not pass all the test cases.
Is it because the moment i change that line and return true, i would not be checking the rest of the tree?

The code does not pass all the test cases. This is confusing to me because I feel like both statements are saying the same thing.
There are two problems here, the first one can be fixed easily, the latter requires a more extensive code rewrite.
First of all, the negation of x<y is x≥y. Indeed, with x<y we exclude the possibility that x = y, but if we negate the condition, we should allow this case.
Next you can not just return true if the node has a value between min and max. A tree. Indeed: if the node is between the bounds that is good news, but the children of the node can still not be valid binary search trees, and thus we need to recurse on the children.
We can thus write this as:
if(min <= tree.value && tree.value < max){
return isValid(tree.left,min,tree.value) && isValid(tree.right,tree.value,max);
}
return false;
Note that, depending on how you exactly implemented the search tree, you need to alter tree.value < max to tree.value <= max as well. Since in some trees (like balanced ones), both the left and the right subchild sometimes contain equivalent values. This however might not be very important if your search tree only contains distinct values, which usually is the case.

Related

Binary search for first occurrence of k

I have code that searches a sorted array and returns the index of the first occurrence of k.
I am wondering whether its possible to write this code using
while(left<right)
instead of
while(left<=right)
Here is the full code:
public static int searchFirstOfK(List<Integer> A, int k) {
int left = 0, right = A.size() - 1, result = -1;
// A.subList(left, right + 1) is the candidate set.
while (left <= right) {
int mid = left + ((right - left) / 2);
if (A.get(mid) > k) {
right = mid - 1;
} else if (A.get(mid) == k) {
result = mid;
// Nothing to the right of mid can be the first occurrence of k.
right = mid - 1;
} else { // A.get(mid) < k
left = mid + 1;
}
}
return result;
}
How do I know when to use left is less than or equal to right, or just use left is less than right.
Building on this answer to another binary search question: How can I simplify this working Binary Search code in C?
If you want to find the position of the first occurrence, you can't stop when you find a matching element. Your search should look like this (of course this assumes that the list is sorted):
int findFirst(List<Integer> list, int valueToFind)
{
int pos=0;
int limit=list.size();
while(pos<limit)
{
int testpos = pos+((limit-pos)>>1);
if (list.get(testpos)<valueToFind)
pos=testpos+1;
else
limit=testpos;
}
if (pos < list.size() && list.get(pos)==valueToFind)
return pos;
else
return -1;
}
Note that we only need to do one comparison per iteration. The binary search finds the unique position where all the preceding elements are less than valueToFind and all the following elements are greater or equal, and then it checks to see if the value you're looking for is actually there.
The linked answer highlights several advantages of writing a binary search this way.
Simply put No.
Consider the case of array having only one element i.e., {0} and the element to be searched is 0 as well.
In this case, left == right, but if your condition is while(left<right), then searchFirstOfK will return -1.
This answer is in context of the posted code. If we are talking about alternatives so that we can use while(left<right) then Matt Timmermans's answer is correct and is an even better approach.
Below is a comparison of Matt (OP - Let's call it Normal Binary) and Matt Timmermans (Let's call it Optimized Binary) approaches for a list containing values between 0 and 5000000:
This is an extremely interesting question. The thing is there is a way by which you can make your binary search right always. The thing is determining the correct ranges and avoiding the single element stuck-out behavior.
while(left+1<right)
{
m = (left+right)/2;
if(check condition is true)
left = m;
else
right = m;
}
Only key thing to remember is you always make the left as the smallest condition unsatisfying element and right as the biggest condition satisfying element. That way you won't get stuck up. Once you understand the range division by this method, you will never fail at binary search.
The above initialization will give you the largest condition satisfying element.
By changing the initialization you can get variety of elements (like small condition satisfying element).

How do i calculate space complexity for checking if binary search tree is balanced?

I want to check if binary search tree provided to me is balanced or not.
Since tree already exists in memory, there is no additional storage needed while checking if tree is balanced when traversing through nodes.
So I assume space complexity would be O(1).
Is it correct?
// Definition for binary tree
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
if (getHeight(root) == -1)
return false;
return true;
}
public int getHeight(TreeNode root) {
if (root == null)
return 0;
int left = getHeight(root.left);
int right = getHeight(root.right);
if (left == -1 || right == -1)
return -1;
if (Math.abs(left - right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
}
Your algorithm is O(height) space, not O(1) - you need to store 1 recursive function call in memory for every node as you recurse down the tree, and you can never go deeper than O(height) in the tree (before you return and can get rid of the already-fully-processed nodes).
For a tree like:
(Image reference - Wikipedia)
Your calls will go like this:
getHeight(8)
getHeight(3)
getHeight(1)
getHeight(6)
getHeight(4)
getHeight(7)
getHeight(10)
getHeight(14)
getHeight(13)
Here, getHeight(8) calls getHeight(3), which calls getHeight(1) and getHeight(6), etc.
After we've finished calling the function for 1 (returning the result to the call for 3), we don't need to keep that in memory any more, thus the maximum number of calls that we keep in memory is equal to the height of the tree.
It can be done in O(1) space, but it's fairly complicated and really slow (much slower than the O(n) that your solution takes).
The key is that we have a binary search tree, so, given a node, we'd know whether that node is in the left or right subtree of any ancestor node, which we can use to determine the parent of a node.
I may create a separate Q&A going into a bit more details at some point.

Data Structure for storing ranges of values that allows efficient comparision operation

I am looking for a data structure that allows storing non-overlapping ranges of integers
and comparing whether a certain range exists[is covered] in[by] the data structure.
For example, after I store (0,9),(10,19),(30,29),
at some point later I want to check if the range (1,11) is covered, in which case the
algorithm gives a "yes" whereas with the range (15,25) the algorithm gives a "no" as the given range is not covered.
Many thanks in advance.
Since you're dealing with non-overlapping ranges of integers, I think a simple BST could do the job(balanced like AVL or RB-tree, in case you want strict O(logN) performance)
For intervals [a-b]
Build the tree keeping 'a' as the key.
Node structure would be something like:
struct node{
int left;
int right;
struct node*left;
struct node*right;
};
In order to search:
bool SearchOverlap(node* root, interval I){
if(!root)
return false;
if(I.right < root->left)
SearchOverlap(root->left, I);
else if(I.left > root->right)
SearchOverlap(root->right, I);
else if(I.left > root->left && I.right < root->right)
return true;
else if(I.left < root->left && I.right < root->right)
return SearchOverlap(root->left, new Interval(I.left, root->left));
else if(I.left > root->left && I.right > root->right)
return SearchOverlap(root->right, new Interval(root->right, I.right));
}
You might be looking for the Interval Tree data structure, which is designed to store and search for intervals fast.

Finding if a Binary Tree is a Binary Search Tree [duplicate]

This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
Today I had an interview where I was asked to write a program which takes a Binary Tree and returns true if it is also a Binary Search Tree otherwise false.
My Approach1: Perform an in-order traversal and store the elements in O(n) time. Now scan through the array/list of elements and check if element at ith index is greater than element at (i+1)th index. If such a condition is encountered, return false and break out of the loop. (This takes O(n) time). At the end return true.
But this gentleman wanted me to provide an efficient solution. I tried but I was unsuccessful, because to find if it is a BST I have to check each node.
Moreover he was pointing me to think over recursion.
My Approach 2: A BT is a BST if for any node N N->left is < N and N->right > N , and the in-order successor of left node of N is less than N and the in-order successor of right node of N is greater than N and the left and right subtrees are BSTs.
But this is going to be complicated and running time doesn't seem to be good. Please help if you know any optimal solution.
It's a pretty well-known problem with the following answer:
public boolean isValid(Node root) {
return isValidBST(root, Integer.MIN_VALUE,
Integer.MAX_VALUE);
}
private boolean isValidBST(Node node, int l, int h) {
if(node == null)
return true;
return node.value > l
&& node.value < h
&& isValidBST(node.left, l, node.value)
&& isValidBST(node.right, node.value, h);
}
The recursive call makes sure that subtree nodes are within the range of its ancestors, which is important. The running time complexity will be O(n) since every node is examined once.
The other solution would be to do an inorder traversal and check if the sequence is sorted, especially since you already know that a binary tree is provided as an input.
The answer provided by #Dhruv is a good one. In addition to that here is one another solution that works in O(n) time.
We need to keep track of the previous node in this approach. In each recursive call we check the previous node data with the current node data. If current node data is less than previous we return false
int isBST(node* root) {
static node* prev = NULL;
if(root==NULL)
return 1;
if(!isBST(root->left))
return 0;
if(prev!=NULL && root->data<=prev->data)
return 0;
prev = root;
return isBST(root->right);
}
boolean b = new Sample().isBinarySearchTree(n1, Integer.MIN_VALUE, Integer.MAX_VALUE);
.......
.......
.......
public boolean isBinarySearchTree(TreeNode node, int min, int max){
if(node == null){
return true;
}
boolean left = isBinarySearchTree(node.getLeft(), min, node.getValue());
boolean right = isBinarySearchTree(node.getRight(), node.getValue(), max);
return left && right && (node.getValue()<max) && (node.getValue()>=min);
}
Comments are invited. Thanks.
I think that the second approach is right. The tree can be traversed in a recursive manner. On each iteration lower and upper bounds of current subtree can be stored. If we want to check subtree with root x, and bounds for the subtree are l and h, then all we need is to check that l <= x <= h and to check the left subtree with bounds l and x, and the right one with bounds x and h.
This will have O(n) complexity, because we start from the root and each node is checked only once as root of some subtree. Also, we need O(h) memory for recursive calls, where h is the height of the tree.
There are some examples above using INTEGER.MAX AND MIN
I cant see a reason to pass them and the significance of it,
correct me if I am wrong in anyway or explain me the reason.
More over binary search tree may have objects which are compared by compareTo method or Coperator.. ( hence Integer.MIN and Integer.MAX dont fit on that model)
I am writing a code where it returns true or false
one has to call (root_node,true) and it will return true if it is a bst else false
void boolean isBSt( node root_node, boolean passed_root)
{
if ( node==null){
if ( passed_root)
return false;
// you have passed null pointer as
//root of the tree , since there is no
// valid start point we can throw an exception or return false
return true;
}
if( node.right !=null )
if ( node.right.data <= node.data)
return false;
if ( node.left !=null )
if ! ( node.left.data <= node.data)
return false;
return ( isBST( node.right , false) && isBST( node.left, false ) )
}
Have a look at this solution:
http://preparefortechinterview.blogspot.com/2013/09/am-i-bst.html
It explains different ways and gives you a generic and efficient method too. Hope it helps.
Here is another Solution which uses 2 helper functions to calculate for each node the min and max value in the subtree using the helper function minValue and maxValue
int isBST(struct node* node)
{
if (node == NULL)
return(true);
/* false if the max of the left is > than us */
if (node->left!=NULL && maxValue(node->left) > node->data)
return(false);
/* false if the min of the right is <= than us */
if (node->right!=NULL && minValue(node->right) < node->data)
return(false);
/* false if, recursively, the left or right is not a BST */
if (!isBST(node->left) || !isBST(node->right))
return(false);
/* passing all that, it's a BST */
return(true);
}

How to verify if a given tree is a Binary Search Tree or not [duplicate]

This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
I wanted to know if a given binary tree is a binary search tree or not.
I don't know How to do that?
The only thing I know is that the inorder traversal of BST will gives you ascending order output.
So, is this the only condition we need to verify or is there anything else we are suppose to check.
In case if there are some other necessary conditions to be checked, What are they? and why those conditions are necessary to be checked? Because, I think, INORDER traversal itself can tell you easily if the given tree is BST or not.
Yes, if inorder traversal of the tree gives you a strictly monotonic list of values that is sufficient to determine that the tree is a BST.
By definition of Binary search tree, if every node of the binary tree satisfy the following conditions then it is a Binary Search Tree:
The left subtree of a node should contain only nodes with keys less than the node’s key
The right subtree of a node should contain only nodes with keys greater than the node’s key
Both the left and right subtrees must also be binary search trees.
All the above conditions are verified if the inorder traversal is in ascending order.
Actually - it is not enough to just do an in order traversal - you also need to verify that each node's value follows the rules of the tree. In the case of a BST, the left child value is less than the node value and the right child value is greater than the node value. Here is a recursive example in Java.
private static boolean isBST(Node current, Comparable more, Comparable less) {
if (current == null)
return true;
if (less != null && current.value.compareTo(less) > 0)
return false;
if (more != null && current.value.compareTo(more) < 0)
return false;
return isBST(current.left, more, current.value) &&
isBST(current.right, current.value, less);
}
public static boolean isBST(BinarySearchTree tree) {
return isBST(tree.getRoot(), null, null);
}
While doing In-Order traversal, we can keep track of previously visited node
Code:
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
A simple but elegant recursive solution in Java:
public static boolean isBST(TreeNode node, int leftData, int rightData)
{
if (node == null) return true;
if (node.getData() > leftData || node.getData() <= rightData) return false;
return (isBST(node.left, node.getData(), rightData)
&& isBST(node.right, leftData, node.getData()));
}
The initial call to this function can be something like this:
if (isBST(root, Integer.MAX_VALUE, Integer.MIN_VALUE))
System.out.println("This is a BST.");
else
System.out.println("This is NOT a BST!");
Essentially we keep creating a valid range (starting from [ MIN_VALUE, MAX_VALUE]) and keep shrinking it down foe each node as we go down recursively.
Source: http://exceptional-code.blogspot.com/2011/08/binary-search-trees-primer.html

Resources