Checking if a tree is binary search tree - java

I am not able to understand how the Java function HERE (Please scroll to the very end of the page) checks if a tree is BST or not, as the code does not look like making using of min and max at all.
I am copy pasting the code here as well
/**
Tests if a tree meets the conditions to be a
binary search tree (BST). Uses the efficient
recursive helper.
*/
public boolean isBST2() {
return( isBST2(root, Integer.MIN_VALUE, Integer.MAX_VALUE) );
}
/**
Efficient BST helper -- Given a node, and min and max values,
recurs down the tree to verify that it is a BST, and that all
its nodes are within the min..max range. Works in O(n) time --
visits each node only once.
*/
private boolean isBST2(Node node, int min, int max) {
if (node==null) {
return(true);
}
else {
// left should be in range min...node.data
boolean leftOk = isBST2(node.left, min, node.data);
// if the left is not ok, bail out
if (!leftOk) return(false);
// right should be in range node.data+1..max
boolean rightOk = isBST2(node.right, node.data+1, max);
return(rightOk);
}
}

A tree is a BST if and only if the nodes of an inorder traversal are monotonic. The easiest way to think of this is that if the root has value n, then the left-hand branch should also be a BST whose nodes are at most n, and the right-hand side should be a BST whose nodes are at least n. If those conditions are satisfied then the tree as a whole is a BST.
That's exactly what your code nearly does. It checks that a tree is a BST with a given minimum a given maximum. It recursively calls itself by looking at the root node with value data, and then checks that the left-hand branch is a BST none of whose nodes exceeds data, and that the right-hand branch is a BST none of whose nodes is smaller than data.
But actually it doesn't quite do this... it misses out the min/max check! Perhaps you're supposed to add that yourself? Is this homework?
The place to add it would be in here:
if (node==null) {
return(true);
}
You just need a couple of extra conditions for if node!=null...

boolean checkBST(Node root) {
return c(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
boolean c(Node n, int s, int b) {
return n == null || (n.data > s && n.data < b && c(n.left, s, n.data) && c(n.right, n.data, b));
}

Related

Height of a binary tree: why is this solution not passing 2/6 test cases in hackerrank?

Wrote a recursive solution for the height of a binary search tree that uses in-order traversal.
Every time the function reaches a "null" node (the end of a line), it resets the variable called "numLevels". Every time the method reaches the end of a line, if numLevels > finalVar, then finalVar becomes numLevels.
This is my solution:
static int finalVar= 0;
static int numLevels= 0;
public static int height(Node root) {
// traverse (in order), ml++ with every recursive call, reset when node == null
findHeight(root);
if (finalVar-1 == 1) return 0; // special case defined in instructions
else{
return finalVar-1;
}
}
public static void findHeight(Node node){
numLevels++; // every time we recursive call, we add
if (node == null){
if (numLevels > finalVar){
finalVar=numLevels;
}
numLevels=0;
return;
}
findHeight(node.left);
findHeight(node.right);
}
and these are the two test cases that it isn't passing:
and:
all the other test cases are passing. Can anyone spot the reason it's not working? :( thanks!
Just spitballing, but wouldn't setting numLevels to 0 also reset it for the other branch? Because remember that your recursive call goes all the way down the furthest left branch, then the branch to the right of the last left. numLevels at that time is 0, which would never be bigger than the other branch.
Since you're making a helper function anyways, there is no reason to have static variables. Just pass along the current max, and the count, and then do everything the same. That way, your current depth is "thread safe" in respect to your recursive depth.

Max heap of nodes java

I currently need to implement a max heap of nodes where my node class keeps track of the data, the parent and then the left and right child. My insert method for max heap is taking forever to fill with an array of 100 strings. Here is my code: `
public void insert(String name) {
MyNode node = new MyNode(name);
if (root ==null) {
root = node;
}
else {
MyNode parent = findSpot(root);
if(parent.lChild==null) {
parent.lChild=node;
node.setParent(parent);
}
else {
parent.rChild=node;
node.setParent(parent);
}
}
}
public MyNode findSpot(MyNode curr) {
if (curr.lChild == null) {
return curr;
}
else if (curr.rChild==null) {
return curr;
}
else {
if (findSpot(curr.lChild).findHeight(root, curr, 1) > findSpot(curr.rChild).findHeight(root, curr, 1)) {
return findSpot(curr.lChild);
}
else {
return findSpot(curr.rChild);
}
}
}`
If anyone code offer suggestions or tell me whats wrong that'd be greatly appreciated.
If you want to see why your findSpot function is taking so long, add a line at the beginning that outputs "findSpot <node>", where is the details of the node being searched. You'll find that the recursive algorithm is being called many times. And it looks like findHeight is also being called quite often. I'm not certain, but it looks like you're doing an exhaustive tree search on every insertion.
Binary heaps must maintain the Shape property: it is a complete binary tree except possibly the bottom row, which is left-filled. Because of that, if you know how many nodes are in your heap, you can easily find the insertion spot for the next node. Consider this heap:
1
2 3
4 5 6
There are 6 nodes in the heap. Whenever there are 6 nodes in a heap, the tree will look like this and the insertion spot for the next node will be the right child of the far right node (3 in this case).
The interesting thing is that the binary representation of the node number tells us where that node is. For example, 6 in binary is 110. Lop off the first digit, 1, and you're left with 10. Now, starting at the root and taking the next digit in the number, go left if the digit is 0, and right if the digit is 1. Then take the next digit and do the same thing. Repeat until you run out of digits.
In the case of 6, we'd go right from the root to node 3, and then left to node 6.
When you're adding a new node, increment the count and follow the procedure above to locate the insertion spot. 7 is 111 in binary. You lop off the high bit, leaving 11. Then, starting at the root you go right, and the insertion spot is the right child of node 3.
Of course, once you've placed the node in the tree to satisfy the shape property, you have to do the standard re-heapify to adjust the nodes in the tree so that the heap property is maintained.

String heap not inserting properly

I've been working on my assignment which is to create a heap of strings, and do various functions on it. I'm now testing my code to see if it's inserting properly, and it's not. I'm testing the words: Golf, Bravo, Hotel, Alpha, Delta, Echo, Charlie, Foxtrot which would insert them alphabetically however when I print my heap I end up with:
Alpha
Bravo Charlie
Foxtrot Delta Hotel Echo
Golf
Here is the code that I have written:
public boolean insert(String key) {
if(currentSize == maxSize) {
return false;
}
Node newNode = new Node(key);
heapArray[currentSize] = newNode;
trickleUp(currentSize++);
return true;
}
public void trickleUp(int index) {
int parent = (index - 1) / 2;
Node bottom = heapArray[index];
while(index > 0 && heapArray[parent].getKey().compareTo(bottom.getKey()) > 0) {
heapArray[index] = heapArray[parent];
index = parent;
parent = (parent - 1) / 2;
}
heapArray[index] = bottom;
}
EDIT: After doing a quick search and finding another source code for a Heap, and testing it I was given the same output. Is there a reason why this is not being added alphabetically?
The behaviour you show in your printout is correct for a min heap, see:
http://en.wikipedia.org/wiki/Heap_(data_structure)
From the introductory paragraph (emphasis added):
Either the keys of parent nodes are always greater than or equal to those of the children and the highest key is in the root node (this kind of heap is called max heap) or the keys of parent nodes are less than or equal to those of the children and the lowest key is in the root node (min heap).
From the second paragraph (emphasis added):
there is no implied ordering between siblings or cousins and no implied sequence for an in-order traversal (as there would be in, e.g., a binary search tree). The heap relation mentioned above applies only between nodes and their immediate parents.
Your heap appears correctly ordered, in that each node only has children that are greater than it, alphabetically.

Need help calculating the depth of left and right subbranches any binary tree

I have to write an AVL tree for my data structures course and am stuck on calculating the balance factor for a subtree so that I know where and how to rotate the tree.
Thanks,
Eric
edit:
I know have to count to number of nodes in a binary tree.
private int countTotalNodes(AVLNode<T> start){
AVLNode<T> current = start;
if(current.getLeft() != null){
return countTotalNodes(current.getLeft());
}
if(current.getRight() != null){
return countTotalNodes(current.getRight());
}
return 1;
}
I think the usual implementation for an AVL tree stores the height of a node in the node itself and gets updated in insert, cut-and-link, operations. After those operations we then have to check if the height of the higher up nodes is still correct with something like this:
/**
* Recursively updates heights starting with given node.
* If height of given node is already correct we know
* that we can stop.
*/
private void updateHeights(AvlNode<T> node){
if(node == null) return;
int heightLeft = node.left != null ? node.left.height : -1;
int heightRight = node.right != null ? node.right.height : -1;
int height = heightLeft > heightRight ? heightLeft + 1 : heightRight + 1;
if(node.height != height){
node.height = height;
updateHeights(node.parent);
}
}
That's always called on the parent of the highest changed node so to speak of. Ah good old times - implementing an AVL tree is a fun little project - good luck.. and test it thouroughly!
The usual approach is to add a balance factor field to the data structure of a tree node. Changes to the balance factor happen on inserts and deletes, and the changes propagate as rotations are made to keep things in balance. There's a nice explanation of this, with pseudocode, here.
Computing the balance at each insert or delete (instead of keeping the balance as a bit of extra bookkeeping at each node) makes those operations much more expensive.
Write the method to calculate the depth of a tree and then apply it to left and right sub-trees.
That's the beauty of the tree data structure: it's naturally self-similar and recursive.
Your counting function for number of nodes is wrong (except for very degenerated trees) - it counts either the left or the right subtree, but never both. Try to correct this first.
Then think about how you can use a similar algorithm to construct the depth.
But as said in other answers, don't use this for balancing your tree, as the performance penalty of this will be more than all the benefits of having a balanced tree. Instead store your depth in the nodes and think about when it needs to be adapted.

Calculating longest path

I have a n-ary tree which contains key values (integers) in each node. I would like to calculate the minimum depth of the tree. Here is what I have come up with so far:
int min = 0;
private int getMinDepth(Node node, int counter, int temp){
if(node == null){
//if it is the first branch record min
//otherwise compare min to this value
//and record the minimum value
if(counter == 0){
temp = min;
}else{
temp = Math.min(temp, min);
min = 0;
}
counter++;//counter should increment by 1 when at end of branch
return temp;
}
min++;
getMinDepth(node.q1, counter, min);
getMinDepth(node.q2, counter, min);
getMinDepth(node.q3, counter, min);
getMinDepth(node.q4, counter, min);
return temp;
}
The code is called like so:
int minDepth = getMinDepth(root, 0, 0);
The idea is that if the tree is traversing down the first branch (branch number is tracked by counter), then we set the temp holder to store this branch depth. From then on, compare the next branch length and if it smaller, then make temp = that length. For some reason counter is not incrementing at all and always staying at zero. Anyone know what I am doing wrong?
I think you're better off doing a breadth-first search. Your current implementation tries to be depth-first, which means it could end up exploring the whole tree if the branches happen to be in an awkward order.
To do a breadth-first search, you need a queue (a ArrayDeque is probably the right choice). You'll then need a little class that holds a node and a depth. The algorithm goes a little something like this:
Queue<NodeWithDepth> q = new ArrayDeque<NodeWithDepth>();
q.add(new NodeWithDepth(root, 1));
while (true) {
NodeWithDepth nwd = q.remove();
if (hasNoChildren(nwd.node())) return nwd.depth();
if (nwd.node().q1 != null) q.add(new NodeWithDepth(nwd.node().q1, nwd.depth() + 1));
if (nwd.node().q2 != null) q.add(new NodeWithDepth(nwd.node().q2, nwd.depth() + 1));
if (nwd.node().q3 != null) q.add(new NodeWithDepth(nwd.node().q3, nwd.depth() + 1));
if (nwd.node().q4 != null) q.add(new NodeWithDepth(nwd.node().q4, nwd.depth() + 1));
}
This looks like it uses more memory than a depth-first search, but when you consider that stack frames consume memory, and that this will explore less of the tree than a depth-first search, you'll see that's not the case. Probably.
Anyway, see how you get on with it.
You are passing the counter variable by value, not by reference. Thus, any changes made to it are local to the current stack frame and are lost as soon as the function returns and that frame is popped of the stack. Java doesn't support passing primitives (or anything really) by reference, so you'd either have to pass it as a single element array or wrap it in an object to get the behavior you're looking for.
Here's a simpler (untested) version that avoids the need to pass a variable by reference:
private int getMinDepth(QuadTreeNode node){
if(node == null)
return 0;
return 1 + Math.min(
Math.min(getMinDepth(node.q1), getMinDepth(node.q2)),
Math.min(getMinDepth(node.q3), getMinDepth(node.q4)));
}
Both your version and the one above are inefficient because they search the entire tree, when really you only need to search down to the shallowest depth. To do it efficiently, use a queue to do a breadth-first search like Tom recommended. Note however, that the trade-off required to get this extra speed is the extra memory used by the queue.
Edit:
I decided to go ahead and write a breadth first search version that doesn't assume you have a class that keeps track of the nodes' depths (like Tom's NodeWithDepth). Once again, I haven't tested it or even compiled it... But I think it should be enough to get you going even if it doesn't work right out of the box. This version should perform faster on large, complex trees, but also uses more memory to store the queue.
private int getMinDepth(QuadTreeNode node){
// Handle the empty tree case
if(node == null)
return 0;
// Perform a breadth first search for the shallowest null child
// while keeping track of how deep into the tree we are.
LinkedList<QuadTreeNode> queue = new LinkedList<QuadTreeNode>();
queue.addLast(node);
int currentCountTilNextDepth = 1;
int nextCountTilNextDepth = 0;
int depth = 1;
while(!queue.isEmpty()){
// Check if we're transitioning to the next depth
if(currentCountTilNextDepth <= 0){
currentCountTilNextDepth = nextCountTilNextDepth;
nextCountTilNextDepth = 0;
depth++;
}
// If this node has a null child, we're done
QuadTreeNode node = queue.removeFirst();
if(node.q1 == null || node.q2 == null || node.q3 == null || node.q4 == null)
break;
// If it didn't have a null child, add all the children to the queue
queue.addLast(node.q1);
queue.addLast(node.q2);
queue.addLast(node.q3);
queue.addLast(node.q4);
// Housekeeping to keep track of when we need to increment our depth
nextCountTilNextDepth += 4;
currentCountTilNextDepth--;
}
// Return the depth of the shallowest node that had a null child
return depth;
}
Counter is always staying at zero because primitives in java are called by value. This means if you overwrite the value in a function call the caller won't see the change. Or if you're familiar with C++ notation it's foo(int x) instead of foo(int& x).
One solution would be to use an Integer object since objects are call-by-reference.
Since you're interested in the minimum depth a breadth first solution will work just fine, but you may get memory problems for large trees.
If you assume that the tree may become rather large an IDS solution would be the best. This way you'll get the time complexity of the breadth first variant with the space complexity of a depth first solution.
Here's a small example since IDS isn't as well known as its brethren (though much more useful for serious stuff!). I assume that every node has a list with children for simplicity (and since it's more general).
public static<T> int getMinDepth(Node<T> root) {
int depth = 0;
while (!getMinDepth(root, depth)) depth++;
return depth;
}
private static<T> boolean getMinDepth(Node<T> node, int depth) {
if (depth == 0)
return node.children.isEmpty();
for (Node<T> child : node.children)
if (getMinDepth(child, depth - 1)) return true;
return false;
}
For a short explanation see http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search

Categories