Here is my attempt to check whether a tree is a BST or not:
public boolean isBST() {
return isBSTRecursively(this.root, new Max());
}
class Max {
int value;
}
private boolean isBSTRecursively(Node node, Max max) {
if (node == null) return true; // to handle null root
// to handle scenario when both child nodes are absent
if(node.getLeft() == null && node.getRight() == null) {
max.value = node.getValue();
return true;
}
// if left child is absent, we only investigate right subtree
if(node.getLeft() == null) {
Max rightMax = new Max();
boolean isRightBST = isBSTRecursively(node.getRight(), rightMax);
max.value = Math.max(node.getValue(), rightMax.value);
if(isRightBST && node.getValue() < rightMax.value) {
return true;
} else {
return false;
}
} else {
Max leftMax = new Max();
boolean isLeftBST = isBSTRecursively(node.getLeft(), leftMax);
// if right child is absent, we only investigate left subtree
if(node.getRight() == null) {
max.value = Math.max(node.getValue(), leftMax.value);
if(isLeftBST && node.getValue() > leftMax.value) {
return true;
} else {
return false;
}
} else {
// we investigate both left and right subtrees
Max rightMax = new Max();
boolean isRightBST = isBSTRecursively(node.getRight(), rightMax);
max.value = Math.max(Math.max(leftMax.value, node.getValue()), rightMax.value);
if(isLeftBST && isRightBST && leftMax.value < node.getValue() && node.getValue() < rightMax.value) {
return true;
} else {
return false;
}
}
}
Code works fine as tested with multiple test cases.
But I am not sure if this is a good, clean approach.
Recursive method is big it seems. I am dealing with scenarios like null left node, null right node, node itself null, both child nodes null etc. separately. I guess they all can be handled in a much smaller, and cleaner way.
Moreover, I am always more inclined towards iterative approach(I generally find it better to visualize). Would that be better here (given it can be done iteratively)?
Any suggestions?
A cleaner recursive approach
You could use a bounded approach, i.e. have two variables for every recursion: min and max.
Initially min = INT_MIN and max = INT_MAX
if node = NULL then return True because an empty BST is a BST
else check if node.val < min or node.val > max if this condition is True then tree is not a BST, return False Notice : the strict inequality > and < are used as BST doesn't allow duplicate elements.
recurse for left : recur(node.left) with min remaining the same and max = node.val - 1 because the left subtrees should have values not greater than node.val - 1.
The max cannot be node.val because BST cannot have duplicate elements.
Store the boolean return value in say left
recurse for right : recur(node.right) with min = node.val + 1 and max remaining the same.
The right subtrees should have values not less than node.val + 1.
Store the boolean return value in say right
return left && right
#Aditya gave the ingredients of the more elegant solution.
It is generally not forbidden for a binary search tree to have duplicate values, so there should no be reduction of the "window" with 1.
Here is suggested code:
public boolean isBST() {
return isBSTRecursively(this.root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private boolean isBSTRecursively(Node node, int min, int max) {
return node == null
|| node.getValue() >= min && node.getValue() <= max
&& isBSTRecursively(node.getLeft(), min, node.getValue())
&& isBSTRecursively(node.getRight(), node.getValue(), max);
}
Related
Trying to solve this LC Easy: https://leetcode.com/problems/minimum-depth-of-binary-tree/
Which is to find the minimum depth (number of nodes on shortest path) of a tree.
I was able to create a "findheight" function which gives me the height of a tree.
My logic was to use findheight to find the height of both subtrees (left and right) of a root node, and then return the minimum between the two heights.
class Solution {
public int minDepth(TreeNode root) {
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
return Math.min(left,right) + 1 ;
}
public int findHeight(TreeNode root){
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
return Math.max(left,right) + 1;
}
}
It won't pass the test case:
[-9,-3,2,null,4,4,0,-6,null,-5]
Or:
Output:
4
Expected:
3
My thought process right now is that when I use "findHeight", I'm returning back the 'max' height per left and right subtree. In this test case, I should be returning back the minimum height.
I changed my code to "Math.min" in another iteration, but that doesn't work either.
Any ideas or theories why? So confused!! Should I just abandon this approach altogether?
Issue in current code
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
The above lines of code checks the imbalance only at root level. It does not recursively check imbalance at lower levels.
Check imbalance at every level
public int minDepth(final TreeNode node) {
if (node == null) {
return 0;
}
final int left = minDepth(node.left);
final int right = minDepth(node.right);
// if both paths exist, then return the minimum
if (node.left != null && node.right != null) {
return Math.min(left, right) + 1;
} else {
// if zero or one path exists return that path (so take maximum)
return Math.max(left, right) + 1;
}
}
Long story short, I'm supposed to make a code that inserts, deletes, searches for and prints numbers in a skip list with the first node being negative infinity and the last node being positive infinity (-inf > (...) > inf). I called my search function from my insert function to find a spot to insert any new nodes (only after the third node has been inserted) and I initialize or reference my nodes outside the main function rather than inside of it (although I'm debating on whether or not I should do the latter instead). However one of my functions may be stuck in a loop.
static Node search(double item, double max) {
Node head2 = head;
head2 = Start(head2, max);
//starts at the first highest node in the skiplist
//{... } //find a specific node in a skiplist
return head2;
}
//find first highest node for the search function
static Node Start(Node head2, double max) {
System.out.println(head.key + " " + head.level);
Node s = new Node();
if (head2.max < max) {
s = Start(head2.next, max);
return s;
}
else if (head2.max >= max && head2.inf == false) {
if (head2.level < head2.max) {
s = Start(head2.up, max);
return s;
}
else if (head2.level == head2.max) {
s = head;
return s;
}
}
return s;
}
The start function is called from the search function (called in order of main > double insert > Node search > Node start) and it is supposed to find the first node of the highest level. Once it does so, It returns that node to the search function so it can start it's search from there. But when called, it simply goes blank and nothing happens despite continuing to run. When I put in a print function to determine the problem, it simply prints the first node's key and 1st level and goes blank from there. UPDATE: I've learned that the function is able to find the node but it can't return it via recursion. I would like to find a way to fix that.
The problem was actually in my search function.
for(j = max; j >= 1; j--) {
while(head2.next != last && head2.key != item && i == 0) {
if(item > head2.key && head2.next != last) {
head2 = head2.next;
}
else if(item < head2.key || head2.next == last) {
head2 = head2.prev;
i = 1;
}
}
(...)}
this was the function that kept looping so I had to change the statement for while by having it say this instead
while(head2.next != last && head2.key < item && head2.inf != true && i == 0)
I wrote a method to return the height of a Binary Search Tree.
Now I am trying to return height - 1 from the recursive method. I am doing this by adding extra if conditions.
Is there a better way to return the value - 1 from the recursive function?
static int height(Node root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right==null) {
return 1;
} else
// I want to return height - 1.
// For example if max height is 10, I wanted to return 9.
return (1 + Math.max(height(root.left), height(root.right));
}
}
In your base cases return -1 and 0 respectively:
static int height(Node root) {
if(root == null)
return -1;
if(root.left == null && root.right==null)
return 0;
else
return 1+ Math.max(height(root.left),
height(root.right));
}
Update to comply with requirement mentioned in comment: "What if I wanted to return 0 for null node, 1 for single node and if height-1 for all other."
static int funny_height(Node root) {
int h = height(node);
return h <= 0 ? h + 1 : h;
}
I have a binary search tree where i have to implement a method called
int valueAtPosition(int x)
The problem is, that i need the position in an in order traversal.
To find the in order traversal i have this the following code, but i don't know how i count the recursive calls, to get the right position.
public void inOrderTraverseTree(Node root){
if(root != null){
inOrderTraverseTree(root.leftChild);
System.out.println(root);
inOrderTraverseTree(root.rightChild);
}
}
I think the other solutions are O(n). All you need for this is a count of the children for each node for O(log n).
When you insert a node, for each node you traverse you increase the counter on the traversed node by one.
You need to maintain these counters when deleting, rebalancing, etc which normally isn't difficult.
With this you can get the position of the node when inserted, find the position of a node by value or find a node by position.
To find a node by position is the same kind of binary traversal as for finding by value. If you want the item at position 1000 then you start at the root. No root, not item at that position. Then you look at the left child (you can do it in the other order too and switch ascending/descending), on the left if the left child exists the number of children on the left is 0 plus the count of the children on the left node. Let say in this scenario that the left exists and has 500 children. Then you know 1000 can't be left because there aren't enough items on the left, so it must be right. You can repeat this also checking for bounds all the way down.
For simple O(n) in order traversal if you have a global counter you just increase it only after traversing the left. That should do the same as a depth first search. No need for decreasing and increasing counters or pushing and popping on a stack. You can also have your functions return a count.
public int inOrderTraverseTree(Node root){
if(root == null)
return 0;
int count = inOrderTraverseTree(root.leftChild);
count++;
count += inOrderTraverseTree(root.rightChild);
return count;
}
This approach only becomes annoying if you want to return the node as well.
You can of course replace a recursive function with your own stack but this is a rarely needed performance optimisation and you'll be far better off with the O(log n) solution if you need performance than an optimised custom stack based solution.
You can also use a counter in the recursive approach. However, you can't simply pass an int counter argument - you need all calls to see the "same" counter, so you will have to wrap it in a class (or, as in this case, an inner class):
public static class Counter {
private int value;
public Counter(int initialValue) { value = initialValue; }
public boolean decrement() { value--; return value == 0; }
public boolean expired() { return value <= 0; }
}
public Node inOrderTraverseTree(Node root, Counter counter){
if (root != null && ! counter.expired()) {
Node left = inOrderTraverseTree(root.leftChild, counter);
if (left != null) {
return left;
} else if (counter.decrement()) {
return root;
} else {
return inOrderTraverseTree(root.rightChild, counter);
}
} else {
return null;
}
}
To find the 9th node in-order (using 1-based indexing), you would call this as
Node the9th = inOrderTraverseTree(root, new Counter(9));
If there is no 9th node, it would return null. If you want to use 0-based indexing instead, change { value--; return value == 0; } to { return value-- == 0; }
The iterative in-order traversal approach makes this pretty easy. Increment a counter whenever a node is popped from the stack. When the counter is equal to x, return the value of the node.
Integer valueAtPosition(int x, Node root) {
int count = 0;
List<Node> stack = new ArrayList<>();
Node node = root;
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.add(node);
node = node.leftChild;
} else {
node = stack.pop();
if (count == x) {
return node.value;
}
count++;
node = node.rightChild;
}
}
return null;
}
Recursive version requires passing a mutable wrapper for a counter like so:
public class Counter {
int count = 0;
}
public void inOrderTraverseTree(Node root, int index, Counter counter){
if(root == null || counter.count > index) {
return;
}
inOrderTraverseTree(root.leftChild);
if (counter.count == index) {
System.out.println(root);
}
counter.count = counter.count + 1;
inOrderTraverseTree(root.rightChild);
}
Following is recursive in-order traversal approach: (in c++)
bool valueAtPositionUtil(struct treeNode *root, int &currIndex, int i, int &value) {
if(root != NULL) {
if(valueAtPositionUtil(root->left, currIndex, i, value)) {
return true;
}
if(currIndex == i) {
value = root->data;
return true;
}
currIndex++;
if(valueAtPositionUtil(root->right, currIndex, i, value)) {
return true;
}
}
return false;
}
int ValueAtPosition(int i, struct treeNode *root) {
int value = 0;
int currIndex = 0;
if(valueAtPositionUtil(root, currIndex, i, value)) {
return value;
}
//index out of bound
// you can return according your problem
return -1;
}
I am currently coding a recursive method to return the max imbalance on the whole of a Binary Search Tree. I've very new to recursive programming so it's quite difficult to wrap my head around. The tree I have built has an Imbalance of 1 but my method only returns 0. I'm sure my logic here is flawed.
I'm 100% sure its running " (root == null){ return 0;} " in every step of the method. I tried removing it and defining it further and it continues to do the same.
This is my current method:
public int getMaxImbalance(){
return Math.abs(getMaxImbalance(root));
}
public int getMaxImbalance (TreeNode<E> root){
if (root == null){
return 0;
}else if(root.left != null && root.right == null){
return 1 + getMaxImbalance(root.left) + getMaxImbalance(root.right);
//adds 1 left is true and right is false
}else if(root.left == null && root.right != null){
return -1 + getMaxImbalance(root.left) + getMaxImbalance(root.right);
//adds -1 left is false and right is true
}
return getMaxImbalance(root.left) + getMaxImbalance(root.right);
//calls itself if both fields are null;
}
The logic in your code seems wrong: the max imbalance of a node is not the sum of the max imbalance of its child(ren). Rather, the max imbalance should be the abs of the difference of the height of its child(ren) (if one of them is empty the max imbalance of that node is just 0, so the max imbalance of the current node depends entirely on it's only child).