Aim: Find if a tree is a balanced binary tree.
I have implemented a program that does work, but wanted to make it more efficient by preventing unnecessary recursion. To do this I am using a static variable, that is set when even a single condition is evaluated to false, so that every other recursive call returns, before making any of their own recursive calls.
static int shouldIExit=0;
public boolean isBalanced(TreeNode root) {
if(root==null){
return true;
}
if(shouldIExit==1 || Math.abs(height(root.left)-height(root.right))>1){
height(root.right))>1: "+ (Math.abs(height(root.left)-height(root.right))>1) ) ;
shouldIExit=1;
return false;
}
else{
return (isBalanced(root.left) && isBalanced(root.right) );
}
}
The problem is that the static variable is somehow being set even when no condition causes it to do so. i.e., shouldIExit is set to 1 even when the if condition corresponding to it, does not evaluate to true.
Is this me not understanding how static variables work?
You don't need a static variable. It's usually bad practice to use non-local variables (either static or instance variables) in a recursive method.
public boolean isBalanced(TreeNode root) {
if(root==null) {
return true;
}
if(Math.abs(height(root.left)-height(root.right))>1) {
return false;
} else{
return (isBalanced(root.left) && isBalanced(root.right) );
}
}
You could save some work if you combine the logic of height and isBalanced. I believe something like this should work:
public boolean isBalanced (TreeNode root) {
return balancedHeight(root) >= 0;
}
public int balancedHeight (TreeNode root) {
if (root == null) {
return 0; // an empty tree is balanced
}
int left = balancedHeight(root.left);
if (left < 0) {
return -1; // left sub-tree is not balanced, so entire tree is not balanced
}
int right = balancedHeight(root.right);
if (left == right) { // the tree is balanced if both sub-trees are balanced
// and both have same height
return left + 1;
} else {
return -1; // tree is not balanced - either the right sub-tree is not
// balanced or the two sub-trees have different heights
}
}
Related
I'm learning the BST recursive construction and found that the insert method does not use return keyword when implementing recursion, but the contains method do use the return key word. Can anybody explain this to me? Many thanks!
static class BST {
public int value;
public BST left;
public BST right;
public BST(int value) {
this.value = value;
}
public BST insert(int value) {
// Write your code here.
// Do not edit the return statement of this method.
if (value < this.value) {
if (left == null) {
BST newBST = new BST(value);
left = newBST;
} else {
left.insert(value);
}
} else {
if (right == null) {
BST newBST = new BST(value);
right = newBST;
} else {
right.insert(value);
}
}
return this;
}
public boolean contains(int value) {
// Write your code here.
if (value < this.value) {
if (left == null) {
return false;
} else {
return left.contains(value);
}
} else if (value > this.value) {
if (right == null) {
return false;
} else {
return right.contains(value);
}
} else{
return true;
}
}
Essentially because insert is not implemented as a function but contains is, meaning that insert just has side effects, it changes the state of BST. Contains is inherently a function - it returns an answer for a given input.
The fact insert returns this at the end is not necessary, it could just as easily have a void return value.
A functional version would return a new BST that is like the original but with the element inserted, and that would require use of the returned value, there would be a bit more complexity there.
(I'm not advocating a functional version here!)
The "insert" function only has a return statement right at the end, because all it has to return is "this", rather than being dependent on outside factors and the execution of the function.
So, short version: You use "return" when you need to, and you do not use "return" when you do not need to.
I am currently writing a method that removes a given value from a binary search tree. However when I call it, it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
There are two methods, one that find the elements, and the other that deletes it.
Here is the one that finds that element...
public static TreeNode delete(TreeNode t, Comparable x, TreeDisplay display)
{
if( x.compareTo(t.getValue()) > 0)
{
display.visit(t);
t.setRight(delete( t.getRight(), x, display));
}
else if ( x.compareTo(t.getValue()) < 0)
{
display.visit(t);
t.setLeft(delete(t.getLeft(), x, display));
}
else
{
t = deleteNode(t, display);
}
return t;
This is the method that deletes the value
private static TreeNode deleteNode(TreeNode t, TreeDisplay display)
{
if (t.getRight()!=null)
{
TreeNode right = t.getRight();
TreeNode max = (TreeNode)TreeUtil.leftmost(right);
TreeNode previous = null;
while ( right.getLeft()!=null&&right.getLeft().getLeft()!=null)
{
right = right.getLeft();
}
t.setValue(max.getValue());
if ( max.getRight()==null)
{
right.setLeft(null);
}
else
{
right.setLeft(max.getRight());
}
}
else if (t.getLeft() !=null)
{
TreeNode left = t.getLeft();
TreeNode max = (TreeNode)TreeUtil.rightmost(left);
while(left.getRight()!=null &&left.getRight().getRight()!=null)
{
left = left.getRight();
}
t.setValue(max.getValue());
if ( max.getLeft()==null)
{
left.setRight(null);
}
else
{
left.setRight(max.getLeft());
}
}
else
{
t = null;
}
return t;
}
Thanks in advance!
...it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
It's because you're returning the deleted node from deleteNode(), and in the first method delete(), your calls to setRight() and setLeft() are setting every traversed element to the deleted element as the recursion unwinds back up the tree.
I have written a recursive program for checking whether a binary tree is a BST.
I have written a base case which is returning true or false, but I have got confused in recursive case.
This program makes the recursive call but it is not working though I feel its fine.
public class BinaryBSTChecker {
public static boolean isBinaryBST(Node node) {
if ( node != null) {
Node leftNode = node.getLeftNode();
Node rightNode = node.getRightNode();
int value = node.getValue();
isBinaryBST(leftNode) ;
isBinaryBST(rightNode) ;
boolean leftIsOk = isLeftOK(leftNode , value);
boolean rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
}
return false;
}
private static boolean isLeftOK(Node leftNode, int value) {
boolean leftOK = false;
if (leftNode != null) {
if (leftNode.getValue() < value) {
leftOK = true;
}
} else {
leftOK = true;
}
return leftOK;
}
private static boolean isRightOK(Node rightNode, int value) {
boolean rightOK = false;
if (rightNode != null ) {
if (rightNode.getValue() > value) {
rightOK = true;
}
} else {
rightOK = true;
}
return rightOK;
}
}
Client code:
public class TestingClient {
public static void main (String[] args) {
Node node = getBSTTree() ;
System.out.println("------Is Binary BST ?------>"
+ BinaryBSTChecker.isBinaryBST(node));
}
public static Node getBSTTree() {
Node node = new Node(9);
Node leftNode = new Node(7);
Node rightNode = new Node(11);
Node leftNode2 = new Node(67);
Node rightNode2 = new Node(8);
Node leftNode3 = new Node(10);
Node rightNode3 = new Node(12);
node.setLeftNode(leftNode);
node.setRightNode(rightNode);
leftNode.setLeftNode(leftNode2);
leftNode.setRightNode(rightNode2);
rightNode.setLeftNode(leftNode3);
rightNode.setRightNode(rightNode3);
return node;
}
}
The above tree isn't a BST as 67 > 7.
So this should return false, but I am getting true for this case, and in fact for all cases.
why are you returning false at end of public static boolean isBinaryBST(Node node) ?
Return true there and should be ok.
edit:
obviously it was a mistake but i did not take a good look at code.
One more thing here.
There is only isLeftOK and isRightOk called, but also on left & right nodes but there are also calls
isBinaryBST(leftNode) ;
isBinaryBST(rightNode);
It seems that results of those are ignored and this is an issue.
return should be sth like:
return (leftIsOk && rightIsOk && isBinaryBST(leftNode) && isBinaryBST(rightNode));
You're ignoring the return value of isBinaryBST in the recursive calls, so the function just returns whether the root's children is correct.
But the way you tried to solve the problem fundamentally won't work.
Take this tree:
5
/
3
\
7
It's not a valid BST, as 7 > 5.
There's no way you can check for this by only looking at the direct children.
The recommended approach would be passing in a min and max to your function, i.e. the signature would be:
boolean isBinaryBST(Node node, int min, int max)
And simply checking whether the current node's value is between the two (or the node is null) (no need for helper functions), and making the appropriate recursive calls to the children (and remember to check their return values!). The general idea would be: (pseudo-code)
return (current node is between min and max)
&& (left subtree is okay, i.e. recursive call with left child)
&& (right subtree is okay, i.e. recursive call with right child)
I'll leave the exact details to you to work out.
In the above example, when we get to 7, min = 3 and max = 5, so we see that 7 > max, and return false.
Add null checks or it will go in infinite loop
if(leftNode != null)
isBinaryBST(leftNode) ;
if(rightNode != null)
isBinaryBST(rightNode) ;
boolean leftIsOk = true;
boolean rightIsOk = true;
if(leftNode != null)
leftIsOk = isLeftOK(leftNode , value); ;
if(rightNode != null)
rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
I know that you can simply solve this question iteratively by using a counter to increment each time you pass a node in linkedlist; also creating an arraylist and setting the data found with each node inside it. Once you hit the tail of the linkedlist, just minus the Nth term from the total number of elements in the arraylist and you will be able to return the answer. However how would someone perform this using recursion? Is it possible and if so please show the code to show your genius :).
Note: I know you cannot return two values in Java (but in C/C++, you can play with pointers :])
Edit: This was a simple question I found online but I added the recursion piece to make it a challenge for myself which I've come to find out that it may be impossible with Java.
The trick is to do the work after the recursion. The array in the private method is basically used as a reference to a mutable integer.
class Node {
Node next;
int data;
public Node findNthFromLast(int n) {
return findNthFromLast(new int[] {n});
}
private Node findNthFromLast(int[] r) {
Node result = next == null ? null : next.findNthFromLast(r);
return r[0]-- == 0 ? this : result;
}
}
As a general rule, anything that can be done with loops can also be done with recursion in any reasonable language. The elegance of the solution may be wildly different. Here is a fairly java idiomatic version. I've omitted the usual accessor functions for brevity.
The idea here is to recur to the end of the list and increment a counter as the recursion unwinds. When the counter reaches the desire value, return that node. Otherwise return null. The non-null value is just returned all the way tot the top. Once down the list, once up. Minimal arguments. No disrespect to Adam intended, but I think this is rather simpler.
NB: OP's statement about Java being able to return only one value is true, but since that value can be any object, you can return an object with fields or array elements as you choose. That wasn't needed here, however.
public class Test {
public void run() {
Node node = null;
// Build a list of 10 nodes. The last is #1
for (int i = 1; i <= 10; i++) {
node = new Node(i, node);
}
// Print from 1st last to 10th last.
for (int i = 1; i <= 10; i++) {
System.out.println(i + "th last node=" + node.nThFromLast(i).data);
}
}
public static void main(String[] args) {
new Test().run();
}
}
class Node {
int data; // Node data
Node next; // Next node or null if this is last
Node(int data, Node next) {
this.data = data;
this.next = next;
}
// A context for finding nth last list element.
private static class NthLastFinder {
int n, fromLast = 1;
NthLastFinder(int n) {
this.n = n;
}
Node find(Node node) {
if (node.next != null) {
Node rtn = find(node.next);
if (rtn != null) {
return rtn;
}
fromLast++;
}
return fromLast == n ? node : null;
}
}
Node nThFromLast(int n) {
return new NthLastFinder(n).find(this);
}
}
Okay, I think think this should do the trick. This is in C++ but it should be easy to translate to Java. I also haven't tested.
Node *NToLastHelper(Node *behind, Node *current, int n) {
// If n is not yet 0, keep advancing the current node
// to get it n "ahead" of behind.
if (n != 0) {
return NToLastHelper(behind, current->next, n - 1);
}
// Since we now know current is n ahead of behind, if it is null
// the behind must be n from the end.
if (current->next == nullptr) {
return behind;
}
// Otherwise we need to keep going.
return NToLastHelper(behind->next, current->next, n);
}
Node *NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n);
}
edit: If you want to return the value of the last node, you can just change it to:
int NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n)->val;
}
This code will fail badly if node is null.
The recursion function:
int n_to_end(Node *no, int n, Node **res)
{
if(no->next == NULL)
{
if(n==0)
*res = no;
return 0;
}
else
{
int tmp = 1 + n_to_end(no->next, n, res);
if(tmp == n)
*res = no;
return tmp;
}
}
The wrapper function:
Node *n_end(Node *no, int n)
{
Node *res;
res = NULL;
int m = n_to_end(no, n, &res);
if(m < n)
{
printf("max possible n should be smaller than or equal to: %d\n", m);
}
return res;
}
The calling function:
int main()
{
List list;
list.append(3);
list.append(5);
list.append(2);
list.append(2);
list.append(1);
list.append(1);
list.append(2);
list.append(2);
Node * nth = n_end(list.head, 6);
if(nth!=NULL)
printf("value is: %d\n", nth->val);
}
This code has been tested with different inputs. Although it's a C++ version, you should be able to figure out the logic :)
I have been trying to learn the ins and outs of some data structures and I am trying to get a binary splay tree to work properly. Every time I run the following code and the node I am looking for is more than one past the root it tells me it is there and then just deletes that whole side from the root down. It works fine if the node is only one level down from the top.
I am not sure what is going wrong but I suppose it has something to do with my rotate functions. I got it to work properly for the insert function which is what I modeled this after.
public class SplayBST {
Node root;
int count;
int level = 0;
boolean found = false;
public SplayBST() {
root = null;
count = 0;
}
public String searchIt(String x) {
//after finishing search method I need to check if splaySearch exists then don't insert just splay it
splaySearch(root, x);
if (this.found == true) {
this.found = false;
return x;
}
else {
return null;
}
}
Node splaySearch(Node h, String x) {
if (h == null) {
return null;
}
if (x.compareTo(h.value) < 0) {
try {
if (x.compareTo(h.left.value) < 0) {
h.left.left = splaySearch(h.left.left, x);
h = rotateRight(h);
} else if (x.compareTo(h.left.value) > 0) {
h.left.right = splaySearch(h.left.right, x);
h.left = rotateLeft(h.left);
}
else {
this.found = true;
return h.left;
}
return rotateRight(h);
}
catch (NullPointerException ex) {
return null;
}
}
else { //basically x.compareTo(h.value)>0
try {
if (x.compareTo(h.right.value) > 0) {
h.right.right = splaySearch(h.right.right, x);
h = rotateLeft(h);
} else if (x.compareTo(h.right.value) < 0) {
h.right.left = splaySearch(h.right.left, x);
h.right = rotateRight(h.right);
}
else {
this.found = true;
return h.right;
}
return rotateLeft(h);
}
catch (NullPointerException ex) {
return null;
}
}
}
Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
return x;
}
Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
return x;
}
class Node {
Node left;
Node right;
String value;
int pos;
public Node(String x) {
left = null;
right = null;
value = x;
}
}
}
I second Tristan Hull's approach to creating a regular BST with a "working" search method. Once you get that working, adding a splay method is rather trivial. I've actually done the same thing when I implemented a Splay Tree in Java. It's a better software design and a simpler implementation.
Your problem is that when you rotate, you update the reference to node H in the function "SplaySearch", but you do not update the parent node in the original "searchIt" function. Thus, the program "thinks" that the original parent node remains the parent, even though the rotated node should be the parent. Thus, when you run whatever method you use to print your tree, you print from a node that is not actually the parent node of the tree, but a child (the level it is on depends on how many times your program called rotateLeft and rotateRight).
To fix this, I suggest implementing search as in a normal binary tree, and then making a "splay" function completely separate from the search function that splays a node to the top of the tree. You would call this splay function at the end of every search, making sure to properly update your reference. This is the traditional way to implement splay trees, and I suggest you take a look at it (maybe look at the wikipedia article on splay trees or do a Google search). Also, you may want to know that your rotate functions are not complete. In terms of splay trees, you also have 2 separate types of double rotations which are very different from single rotations. Again, I suggest looking up splay trees to learn about them more in depth.