Looking for correct recursive algorithm for Leetcode 112 - binary-tree

I am working on Leet Code problem 112. Path Sum:
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
I the code below trying to solve it, but apparently it isn't correct as I keep running into failed test cases.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root.left==null&&root.right==null&&targetSum-root.val ==0)
return true;
else{
if(root.right!= null){
hasPathSum(root.right, targetSum-root.val);
}
if(root.left!=null) {
hasPathSum(root.left, targetSum-root.val);
}
} return false;
}
}
What is wrong with this code?

You are not using the values returned by the recursive calls you make. In a verbose way, you could fix that part of your code as follows:
boolean result = false;
if (root.right != null) {
result = hasPathSum(root.right, targetSum - root.val);
}
if (!result && root.left != null) {
result = hasPathSum(root.left, targetSum - root.val);
}
return result;
It is more compact when you use more logical operators for that:
return root.right != null && hasPathSum(root.right, targetSum - root.val)
|| root.left != null && hasPathSum(root.left, targetSum - root.val);
It is not stated explicitly in the Leet Code challenge, but when calling this function on an empty tree, it should return false. So you should foresee the case where root is null.
The complete solution could look like this:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
return root != null &&
( root.left == null && root.right == null && targetSum == root.val
|| root.right != null && hasPathSum(root.right, targetSum - root.val)
|| root.left != null && hasPathSum(root.left, targetSum - root.val)
);
}
}

Here is my recursive solution in javascript:
var hasPathSum = function(root, targetSum) {
if (root) {
if (!root.left && !root.right) {
return root.val === targetSum;
}
if (root.left) {
const isTherePath = hasPathSum(root.left, targetSum - root.val);
if (isTherePath) return true;
}
if (root.right) {
const isTherePath = hasPathSum(root.right, targetSum - root.val);
if (isTherePath) return true;
}
}
return false;
};

Related

Valid Binary Tree

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
static class ReturnData {
public boolean isBST;
public int max;
public int min;
public ReturnData(boolean is, int mi, int ma) {
isBST = is;
min = mi;
max = ma;
}
}
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
ReturnData res = check(root);
if (res == null) {
return true;
}
return res.isBST;
}
private ReturnData check(TreeNode node) {
if (node == null) {
return null;
}
int min = node.val;
int max = node.val;
ReturnData left = check(node.left);
ReturnData right = check(node.right);
if (left != null) {
min = Math.min(min, left.min);
max = Math.max(max, left.max);
}
if (right != null) {
min = Math.min(min, right.min);
max = Math.max(max, right.max);
}
boolean isBST = true;
if (left != null && (!left.isBST || left.min >= node.val)) {
isBST = false;
}
if (right != null && (!right.isBST || right.min <= node.val)) {
isBST = false;
}
return new ReturnData(isBST, min, max);
}
}
I want to ask a LeetCode question, Question 98.
The question wants me to write an algorithm to check whether the given tree is a valid binary tree, so I wrote like this:
I create a constructor to initialize the return type, which contains the current node's value, max, and min value of its subtree.
I want to use recursion to check the validation.
But it doesn't work, I also check the solution but I still don't know why this way didn't work.
Hope someone could give me a hint, thanks.
The problem is in this condition:
left.min >= node.val
You'll want to see whether the maximum in the left tree exceeds the current node's value, so:
left.max >= node.val

check if tree if complete binary search tree

I'am learning about trees. I just completed problem to check if tree is complete BST or not. I'd like to know if i did it right.
Basically i just have to look for a node which has only one child, for the whole tree.
EDIT: I had definition of both complete and full binary search tree wrong as Mooing Duck pointed out. I finished coding it now, is this the solution?
int heightBST(Node* root)
{
if (root == NULL)
{
return -1;
}
int lHeight = heightBST(root->left);
int rHeight = heightBST(root->right);
return lHeight > rHeight ? 1 + lHeight : 1 + rHeight;
}
int isFullBST(Node* root)
{
if (root == NULL)
{
return 1;
}
int lHeight = heightBST(root->left);
int rHeight = heightBST(root->right);
if (lHeight != rHeight)
{
return -1;
}
if ((root->left == NULL && root->right != NULL) || (root->left != NULL && root->right == NULL))
{
return 0;
}
if (isCompleteBST(root->left) == 0 || isCompleteBST(root->right) == 0)
{
return 0;
}
return 1;
}
int isCompleteBST(Node* root)
{
if (root == NULL)
{
return 1;
}
int lHeight = heightBST(root->left);
int rHeight = heightBST(root->right);
if (lHeight - rHeight != 0 || lHeight - rHeight != 1)
{
return 0;
}
if ((root->left == NULL && root->right != NULL) || (root->left != NULL && root->right == NULL))
{
return 0;
}
if (isCompleteST(root->left) == 0 || isCompleteBST(root->right) == 0)
{
return 0;
}
return 1;
}

Algorithm to print the total sum of all the path

Giving you a binary tree which defined as follows:
public class TreeNode {
public int val;
public TreeNode left, right;
public TreeNode(int val) {
this.val = val;
this.left = this.right = null;
}
}
print the total sum of all the path, a path is defined as the line from the root node to any leaf node
For example:
4 5 6 7 8 10 # # # # 9
should return:
path1: 4 + 5 + 7
path2: 4 + 5 + 8 + 9
path3: 4 + 6 + 10
so the total path sum should be: path1 + path2 + path3
how can we solve the problem by using
recursive
non-recursive
I have find a solution by using non-recursive, but have some little problem about recursive method
Non-Recursive Method:
/**
* non-recursive
*/
public static int pathSum2(TreeNode root) {
int sum = 0;
if (root == null) {
return sum;
}
Queue<TreeNode> queueNode = new LinkedList<TreeNode>();
Queue<Integer> queueSum = new LinkedList<Integer>();
queueNode.add(root);
queueSum.add(root.val);
while (!queueNode.isEmpty()) {
TreeNode node = queueNode.poll();
int temp = queueSum.poll();
if (node.left == null && node.right == null) {
sum += temp;
}
if (node.left != null) {
queueNode.add(node.left);
queueSum.add(node.left.val + temp);
}
if (node.right != null) {
queueNode.add(node.right);
queueSum.add(node.right.val + temp);
}
}
return sum;
}
Recursive Method:
/**
* recursive
*/
public List<List<Integer>> pathSum(TreeNode root) {
List<List<Integer>> rst = new ArrayList<List<Integer>>();
helper(rst, new ArrayList<Integer>(), root);
return rst;
}
public void helper(List<List<Integer>> rst, ArrayList<Integer> list,
TreeNode root) {
if (root == null) {
return;
}
list.add(root.val);
if (root.left == null && root.right == null) {
rst.add(new ArrayList<Integer>(list));
}
helper(rst, list, root.left);
helper(rst, list, root.right);
list.remove(list.size() - 1);
}
but in this way, what I have output is all the path, what if I want to get the total sum of those path?
One way to get the answer is iterator the List> and get the answer but I think it's inefficient. How can we deal with this just in the helper() method because for the sum, java is just pass-by-value
I have find a solution by using recursive
/**
* recursive
*/
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> rst = new ArrayList<List<Integer>>();
helper(rst, new ArrayList<Integer>(), root, sum);
return rst;
}
public void helper(List<List<Integer>> rst, ArrayList<Integer> list,
TreeNode root, int sum) {
if (root == null) {
return;
}
list.add(root.val);
if (root.left == null && root.right == null) {
rst.add(new ArrayList<Integer>(list));
}
helper(rst, list, root.left, sum - root.val);
helper(rst, list, root.right, sum - root.val);
list.remove(list.size() - 1);
}

Find Ancestor method for binary search tree is not working

I had written the method for finding a node's parent in C# (c-sharp) but my code is not working correctly. Exceptions: System.NullReferenceException is thrown when I try to delete a node who's parent is null.
public TreeNode FindParent(int value, ref TreeNode parent)
{
TreeNode currentNode = root;
if (currentNode == null)
{
return null;
}
while (currentNode.value != value)
{
if (value < currentNode.value)
{
parent = currentNode;
currentNode = currentNode.leftChild;
}
if (value > currentNode.value)
{
parent = currentNode;
currentNode = currentNode.rightChild;
}
}
return currentNode;
}
public void Delete(int value)
{
TreeNode parent = null;
TreeNode nodeToDelete = FindParent(value, ref parent);
if (nodeToDelete == null)
{
throw new Exception("Unable to delete node: " + value.ToString());
}
//CASE 1: Nod has 0 children.
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild == null)
{
if (parent.leftChild == nodeToDelete)
{
parent.leftChild = null;
}
if (parent.rightChild == nodeToDelete)
{
parent.rightChild = null;
}
count--;
return;
}
//CASE 2: Nod has 1 left || 1 right barn
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild != null)
{
nodeToDelete.rightChild = parent.rightChild;
nodeToDelete = null;
count--;
return;
}
if (nodeToDelete.leftChild != null && nodeToDelete.rightChild == null)
{
nodeToDelete.leftChild = parent.leftChild;
nodeToDelete = null;
count--;
return;
}
//CASE 3: Nod has 2 children
if (nodeToDelete.rightChild != null && nodeToDelete.leftChild != null)
{
TreeNode successor = LeftMostNodeOnRight(nodeToDelete, ref parent);
TreeNode temp = new TreeNode(successor.value);
if (parent.leftChild == successor)
{
parent.leftChild = successor.rightChild;
}
else
{
parent.rightChild = successor.rightChild; nodeToDelete.value = temp.value;
}
count--;
return;
}
}
since you are using recursion , you don't need the parent Node to delete a node in a binary search tree, here is a delete method where you pass in int and the root
private BinaryTreeNode remove (int value, TreeNode t){
if(t==null)
return t; // not found; do nothing
if(value < t.value){
t.left = remove(x,y,t.left);
}
else if (value > t.value){
t.right = remove(x,y,t.right);
}
else if( t.left!=null && t.right != null) // two children
{
t.info = findMin(t.right).info;
remove(t.info.getLastName(),y,t.right);
}
else{ // one child
if (t.left != null) {
t = t.left;
}
else{
t = t.right;
}
}
return t;
}
Edit-----------findMin (find minimum node in a binary search tree)
private BinaryTreeNode findMin ( BinaryTreeNode t){ // recursive
if(t == null)
return null;
else if (t.left == null)
return t;
return findMin(t.left);
}
So you take the min value from the right subtree, and make it the parent of t.info. Follow these diagrams. We are deleting node 25 with two children.

How do you validate a binary search tree?

I read on here of an exercise in interviews known as validating a binary search tree.
How exactly does this work? What would one be looking for in validating a binary search tree? I have written a basic search tree, but never heard of this concept.
Actually that is the mistake everybody does in an interview.
Leftchild must be checked against (minLimitof node,node.value)
Rightchild must be checked against (node.value,MaxLimit of node)
IsValidBST(root,-infinity,infinity);
bool IsValidBST(BinaryNode node, int MIN, int MAX)
{
if(node == null)
return true;
if(node.element > MIN
&& node.element < MAX
&& IsValidBST(node.left,MIN,node.element)
&& IsValidBST(node.right,node.element,MAX))
return true;
else
return false;
}
Another solution (if space is not a constraint):
Do an inorder traversal of the tree and store the node values in an array. If the array is in sorted order, its a valid BST otherwise not.
"Validating" a binary search tree means that you check that it does indeed have all smaller items on the left and large items on the right. Essentially, it's a check to see if a binary tree is a binary search tree.
The best solution I found is O(n) and it uses no extra space. It is similar to inorder traversal but instead of storing it to array and then checking whether it is sorted we can take a static variable and check while inorder traversing whether array is sorted.
static struct node *prev = NULL;
bool isBST(struct node* root)
{
// 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;
}
Iterative solution using inorder traversal.
bool is_bst(Node *root) {
if (!root)
return true;
std::stack<Node*> stack;
bool started = false;
Node *node = root;
int prev_val;
while(true) {
if (node) {
stack.push(node);
node = node->left();
continue;
}
if (stack.empty())
break;
node = stack.top();
stack.pop();
/* beginning of bst check */
if(!started) {
prev_val = node->val();
started = true;
} else {
if (prev_val > node->val())
return false;
prev_val = node->val();
}
/* end of bst check */
node = node->right();
}
return true;
}
Here is my solution in Clojure:
(defstruct BST :val :left :right)
(defn in-order [bst]
(when-let [{:keys [val, left, right]} bst]
(lazy-seq
(concat (in-order left) (list val) (in-order right)))))
(defn is-strictly-sorted? [col]
(every?
(fn [[a b]] (< a b))
(partition 2 1 col)))
(defn is-valid-BST [bst]
(is-strictly-sorted? (in-order bst)))
Since the in-order traversal of a BST is a non-decrease sequence, we could use this property to judge whether a binary tree is BST or not. Using Morris traversal and maintaining the pre node, we could get a solution in O(n) time and O(1) space complexity. Here is my code
public boolean isValidBST(TreeNode root) {
TreeNode pre = null, cur = root, tmp;
while(cur != null) {
if(cur.left == null) {
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
else {
tmp = cur.left;
while(tmp.right != null && tmp.right != cur)
tmp = tmp.right;
if(tmp.right == null) { // left child has not been visited
tmp.right = cur;
cur = cur.left;
}
else { // left child has been visited already
tmp.right = null;
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
}
}
return true;
}
bool BinarySearchTree::validate() {
int minVal = -1;
int maxVal = -1;
return ValidateImpl(root, minVal, maxVal);
}
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &minVal, int &maxVal)
{
int leftMin = -1;
int leftMax = -1;
int rightMin = -1;
int rightMax = -1;
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value < currRoot->value) {
if (!ValidateImpl(currRoot->left, leftMin, leftMax)) return false;
if (leftMax != currRoot->left->value && currRoot->value < leftMax) return false;
}
else
return false;
} else {
leftMin = leftMax = currRoot->value;
}
if (currRoot->right) {
if (currRoot->right->value > currRoot->value) {
if(!ValidateImpl(currRoot->right, rightMin, rightMax)) return false;
if (rightMin != currRoot->right->value && currRoot->value > rightMin) return false;
}
else return false;
} else {
rightMin = rightMax = currRoot->value;
}
minVal = leftMin < rightMin ? leftMin : rightMin;
maxVal = leftMax > rightMax ? leftMax : rightMax;
return true;
}
"It's better to define an invariant first. Here the invariant is -- any two sequential elements of the BST in the in-order traversal must be in strictly increasing order of their appearance (can't be equal, always increasing in in-order traversal). So solution can be just a simple in-order traversal with remembering the last visited node and comparison the current node against the last visited one to '<' (or '>')."
I got this question in a phone interview recently and struggled with it more than I should have. I was trying to keep track of minimums and maximums in child nodes and I just couldn't wrap my brain around the different cases under the pressure of an interview.
After thinking about it while falling asleep last night, I realized that it is as simple as keeping track of the last node you've visited during an inorder traversal. In Java:
public <T extends Comparable<T>> boolean isBst(TreeNode<T> root) {
return isBst(root, null);
}
private <T extends Comparable<T>> boolean isBst(TreeNode<T> node, TreeNode<T> prev) {
if (node == null)
return true;
if (isBst(node.left, prev) && (prev == null || prev.compareTo(node) < 0 ))
return isBst(node.right, node);
return false;
}
In Java and allowing nodes with same value in either sub-tree:
public boolean isValid(Node node) {
return isValid(node, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private boolean isValid(Node node, int minLimit, int maxLimit) {
if (node == null)
return true;
return minLimit <= node.value && node.value <= maxLimit
&& isValid(node.left, minLimit, node.value)
&& isValid(node.right, node.value, maxLimit);
}
Here is my answer in python, it has all the corner cases addressed and well tested in hackerrank website
""" Node is defined as
class node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
"""
def checkBST(root):
return checkLeftSubTree(root, root.left) and checkRightSubTree(root, root.right)
def checkLeftSubTree(root, subTree):
if not subTree:
return True
else:
return root.data > subTree.data \
and checkLeftSubTree(root, subTree.left) \
and checkLeftSubTree(root, subTree.right) \
and checkLeftSubTree(subTree, subTree.left) \
and checkRightSubTree(subTree, subTree.right)
def checkRightSubTree(root, subTree):
if not subTree:
return True
else:
return root.data < subTree.data \
and checkRightSubTree(root, subTree.left) \
and checkRightSubTree(root, subTree.right) \
and checkRightSubTree(subTree, subTree.right) \
and checkLeftSubTree(subTree, subTree.left)
// using inorder traverse based Impl
bool BinarySearchTree::validate() {
int val = -1;
return ValidateImpl(root, val);
}
// inorder traverse based Impl
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &val) {
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value > currRoot->value) return false;
if(!ValidateImpl(currRoot->left, val)) return false;
}
if (val > currRoot->value) return false;
val = currRoot->value;
if (currRoot->right) {
if (currRoot->right->value < currRoot->value) return false;
if(!ValidateImpl(currRoot->right, val)) return false;
}
return true;
}
bool ValidateBST(Node *pCurrentNode, int nMin = INT_MIN, int nMax = INT_MAX)
{
return
(
pCurrentNode == NULL
)
||
(
(
!pCurrentNode->pLeftNode ||
(
pCurrentNode->pLeftNode->value < pCurrentNode->value &&
pCurrentNode->pLeftNode->value < nMax &&
ValidateBST(pCurrentNode->pLeftNode, nMin, pCurrentNode->value)
)
)
&&
(
!pCurrentNode->pRightNode ||
(
pCurrentNode->pRightNode->value > pCurrentNode->value &&
pCurrentNode->pRightNode->value > nMin &&
ValidateBST(pCurrentNode->pRightNode, pCurrentNode->value, nMax)
)
)
);
}
To find out whether given BT is BST for any datatype, you need go with below approach.
1. call recursive function till the end of leaf node using inorder traversal
2. Build your min and max values yourself.
Tree element must have less than / greater than operator defined.
#define MIN (FirstVal, SecondVal) ((FirstVal) < (SecondVal)) ? (FirstVal):(SecondVal)
#define MAX (FirstVal, SecondVal) ((FirstVal) > (SecondVal)) ? (FirstVal):(SecondVal)
template <class T>
bool IsValidBST (treeNode &root)
{
T min, max;
return IsValidBST (root, &min, &max);
}
template <class T>
bool IsValidBST (treeNode *root, T *MIN , T *MAX)
{
T leftMin, leftMax, rightMin, rightMax;
bool isValidBST;
if (root->leftNode == NULL && root->rightNode == NULL)
{
*MIN = root->element;
*MAX = root->element;
return true;
}
isValidBST = IsValidBST (root->leftNode, &leftMin, &leftMax);
if (isValidBST)
isValidBST = IsValidBST (root->rightNode, &rightMin, &rightMax);
if (isValidBST)
{
*MIN = MIN (leftMIN, rightMIN);
*Max = MAX (rightMax, leftMax);
}
return isValidBST;
}
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;
}
Works Fine :)
Recursion is easy but iterative approach is better, there is one iterative version above but it's way too complex than necessary. Here is the best solution in c++ you'll ever find anywhere:
This algorithm runs in O(N) time and needs O(lgN) space.
struct TreeNode
{
int value;
TreeNode* left;
TreeNode* right;
};
bool isBST(TreeNode* root) {
vector<TreeNode*> stack;
TreeNode* prev = nullptr;
while (root || stack.size()) {
if (root) {
stack.push_back(root);
root = root->left;
} else {
if (prev && stack.back()->value <= prev->value)
return false;
prev = stack.back();
root = prev->right;
stack.pop_back();
}
}
return true;
}
I wrote a solution to use inorder Traversal BST and check whether the nodes is
increasing order for space O(1) AND time O(n). TreeNode predecessor is prev node. I am not sure the solution is right or not. Because the inorder Traversal can not define a whole tree.
public boolean isValidBST(TreeNode root, TreeNode predecessor) {
boolean left = true, right = true;
if (root.left != null) {
left = isValidBST(root.left, predecessor);
}
if (!left)
return false;
if (predecessor.val > root.val)
return false;
predecessor.val = root.val;
if (root.right != null) {
right = isValidBST(root.right, predecessor);
}
if (!right)
return false;
return true;
}
Following is the Java implementation of BST validation, where we travel the tree in-order DFS and it returns false if we get any number which is greater than last number.
static class BSTValidator {
private boolean lastNumberInitialized = false;
private int lastNumber = -1;
boolean isValidBST(TreeNode node) {
if (node.left != null && !isValidBST(node.left)) return false;
// In-order visiting should never see number less than previous
// in valid BST.
if (lastNumberInitialized && (lastNumber > node.getData())) return false;
if (!lastNumberInitialized) lastNumberInitialized = true;
lastNumber = node.getData();
if (node.right != null && !isValidBST(node.right)) return false;
return true;
}
}
Recursive solution:
isBinary(root)
{
if root == null
return true
else if( root.left == NULL and root.right == NULL)
return true
else if(root.left == NULL)
if(root.right.element > root.element)
rerturn isBInary(root.right)
else if (root.left.element < root.element)
return isBinary(root.left)
else
return isBInary(root.left) and isBinary(root.right)
}
Iterative solution.
private static boolean checkBst(bst node) {
Stack<bst> s = new Stack<bst>();
bst temp;
while(node!=null){
s.push(node);
node=node.left;
}
while (!s.isEmpty()){
node = s.pop();
System.out.println(node.val);
temp = node;
if(node.right!=null){
node = node.right;
while(node!=null)
{
//Checking if the current value is lesser than the previous value and ancestor.
if(node.val < temp.val)
return false;
if(!s.isEmpty())
if(node.val>s.peek().val)
return false;
s.push(node);
if(node!=null)
node=node.left;
}
}
}
return true;
}
This works for duplicates.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = int.min, max = int.max):
if node == null:
return true
if node.value <= min || max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
This works even for int.min and int.max values using Nullable types.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = null, max = null):
if node == null:
return true
if min != null && node.value <= min
return false
if max != null && max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
Inspired by http://www.jiuzhang.com/solutions/validate-binary-search-tree/
There are two general solutions: traversal and divide && conquer.
public class validateBinarySearchTree {
public boolean isValidBST(TreeNode root) {
return isBSTTraversal(root) && isBSTDivideAndConquer(root);
}
// Solution 1: Traversal
// The inorder sequence of a BST is a sorted ascending list
private int lastValue = 0; // the init value of it doesn't matter.
private boolean firstNode = true;
public boolean isBSTTraversal(TreeNode root) {
if (root == null) {
return true;
}
if (!isValidBST(root.left)) {
return false;
}
// firstNode is needed because of if firstNode is Integer.MIN_VALUE,
// even if we set lastValue to Integer.MIN_VALUE, it will still return false
if (!firstNode && lastValue >= root.val) {
return false;
}
firstNode = false;
lastValue = root.val;
if (!isValidBST(root.right)) {
return false;
}
return true;
}
// Solution 2: divide && conquer
private class Result {
int min;
int max;
boolean isBST;
Result(int min, int max, boolean isBST) {
this.min = min;
this.max = max;
this.isBST = isBST;
}
}
public boolean isBSTDivideAndConquer(TreeNode root) {
return isBSTHelper(root).isBST;
}
public Result isBSTHelper(TreeNode root) {
// For leaf node's left or right
if (root == null) {
// we set min to Integer.MAX_VALUE and max to Integer.MIN_VALUE
// because of in the previous level which is the leaf level,
// we want to set the min or max to that leaf node's val (in the last return line)
return new Result(Integer.MAX_VALUE, Integer.MIN_VALUE, true);
}
Result left = isBSTHelper(root.left);
Result right = isBSTHelper(root.right);
if (!left.isBST || !right.isBST) {
return new Result(0,0, false);
}
// For non-leaf node
if (root.left != null && left.max >= root.val
&& root.right != null && right.min <= root.val) {
return new Result(0, 0, false);
}
return new Result(Math.min(left.min, root.val),
Math.max(right.max, root.val), true);
}
}
One liner
bool is_bst(Node *root, int from, int to) {
return (root == NULL) ? true :
root->val >= from && root->val <= to &&
is_bst(root->left, from, root->val) &&
is_bst(root->right, root->val, to);
}
Pretty long line though.
Here's a solution in java from sedgewick's algorithm class.
Check the full BST implementation here
I added some explanatory comments
private boolean isBST() {
return isBST(root, null, null);
}
private boolean isBST(Node x, Key min, Key max) {
if (x == null) return true;
// when checking right subtree min is key of x's parent
if (min != null && x.key.compareTo(min) <= 0) return false;
// when checking left subtree, max is key of x's parent
if (max != null && x.key.compareTo(max) >= 0) return false;
// check left subtree and right subtree
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
}
The iterative function checks iteratively whether given tree is a binary search tree.
The recurse function checks recursively whether given tree is a binary search tree or not.
In iterative function I use bfs for checking BST.
In recurse function I use dfs for checking BST.
Both solutions have a time complexity of O(n)
iterative solution has an advantage over recurse solution and that is iterative solution does early stopping.
Even recurse function can be optimized for early stopping by global flag value.
The idea of both the solution is that the left child should be within the range of -infinity to the value of its parent node whihch is the root node
The right child should be within the range of +infinity to the value of its parent node whihch is the root node
And go on comparing the current node's value within the range. If any node's value is not in the range then return False
class Solution:
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return self.iterative(root)
# return self.recurse(root, float("inf"), float("-inf"))
def iterative(self, root):
if not root:
return True
level = [[root, -float("inf"), float("inf")]]
while level:
next_level = []
for element in level:
node, min_val, max_val = element
if min_val<node.val<max_val:
if node.left:
next_level.append([node.left, min_val, node.val])
if node.right:
next_level.append([node.right, node.val, max_val])
else:
return False
level = next_level
return True
def recurse(self, root, maxi, mini):
if root is None:
return True
if root.val < mini or root.val > maxi:
return False
return self.recurse(root.left, root.val-1, mini) and self.recurse(root.right, maxi, root.val+1)
Python implementation example. This example uses type annotations. However since Node class uses itself we need to include as a first line of the module:
from __future__ import annotations
Otherwise, you will get name 'Node' is not defined error. This example also uses dataclass as an example. To check if it's BST it uses recursion for checking left and right nodes values.
"""Checks if Binary Search Tree (BST) is balanced"""
from __future__ import annotations
import sys
from dataclasses import dataclass
MAX_KEY = sys.maxsize
MIN_KEY = -sys.maxsize - 1
#dataclass
class Node:
value: int
left: Node
right: Node
#property
def is_leaf(self) -> bool:
"""Check if node is a leaf"""
return not self.left and not self.right
def is_bst(node: Node, min_value: int, max_value: int) -> bool:
if node.value < min_value or max_value < node.value:
return False
elif node.is_leaf:
return True
return is_bst(node.left, min_value, node.value) and is_bst(
node.right, node.value, max_value
)
if __name__ == "__main__":
node5 = Node(5, None, None)
node25 = Node(25, None, None)
node40 = Node(40, None, None)
node10 = Node(10, None, None)
# balanced tree
node30 = Node(30, node25, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))
# unbalanced tree
node30 = Node(30, node5, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))
BST example
public bool IsBinarySearchTree(TreeNode root)
{
return IsValid(root, long.MinValue, long.MaxValue);
}
private static bool IsValid(TreeNode node, long min, long max)
{
if (node == null)
{
return true;
}
if (node.Value >= max || node.Value <= min)
{
return false;
}
return IsValid(node.Left, min, node.Value) && IsValid(node.Right, node.Value, max);
}
where TreeNode
public class TreeNode
{
public int Value;
public TreeNode Left;
public TreeNode Right;
public TreeNode(int value)
{
Value = value;
}
}
here's the detailed explanation https://codestandard.net/articles/validate-binary-search-tree/
Using inOrder Traversal..
First Adding the tree value to the array with inorder traversal.
Then iterate through the array which add a flag value true to split the elements after the root elements and before the root elements.
counter is added to check if the tree has elements with the same root value.
min and max is set to the range
var isValidBST = function(root)
{
if(!root) return false;
let current = root;
let data = [];
let flag = false;
let counter = 0;
function check(node){
if(node.left){
check(node.left);
}
data.push(node.val);
if(node.right){
check(node.right);
}
}
let min = Number.MIN_SAFE_INTEGER;
let max = root.val;
for(let i = 0; i < data.length; i++){
if(data[i] == root.val){
flag = true;
counter++;
}
if(flag){
if(data[i] < root.val || data[i] < max || counter > 1){
return false;
}
else{
max = data[i];
}
}
else{
if(data[i] > root.val || data[i] <= min|| counter > 1){
return false
}
else {
min = data[i]
}
}
}
return true;
};
We have to recursively ask each node if its left branch and right branch are valid binary search trees. The only thing each time we ask, we have to pass correct left and right boundaries:
class Solution:
def is_bst(self,root:TreeNode):
if not root:
return True
# left and right are boundaries
def dfs(node,left,right):
if not node:
return True
if not (node.val>left and node.val<right):
return False
# when we move right, we update the left, when we move left we update the right
return dfs(node.left,left,node.val) and dfs(node.right,node.val,right)
return dfs(root, float("-inf"), float("+inf"))
Here is the iterative solution without using extra space.
Node{
int value;
Node right, left
}
public boolean ValidateBST(Node root){
Node currNode = root;
Node prevNode = null;
Stack<Node> stack = new Stack<Node>();
while(true){
if(currNode != null){
stack.push(currNode);
currNode = currNode.left;
continue;
}
if(stack.empty()){
return;
}
currNode = stack.pop();
if(prevNode != null){
if(currNode.value < prevNode.value){
return false;
}
}
prevNode = currNode;
currNode = currNode.right;
}
}

Resources