0

Here's my find() method:

public boolean find(int key) {

    BinTreeNode node = findHelper(key, root);
    if (node == null) {
        return false;
    } else {
        return true;
    }
}    


private BinTreeNode findHelper(int key, BinTreeNode node) {
    if (node == null) {
        return null;
    }    
    if(key == node.item) {
        return node;
    }
    else if(key < node.item) {
        return findHelper(key,node.leftChild);
    }
    else {
        return findHelper(key,node.rightChild);
    }
}

Here's my modified code. It still doesn't work :(

public boolean searchNum(BinTreeNode node, int num) {
    if(node == null) {
        return false;
    }
    else {

        int result = num - node.item;
        if(find(result)) {
            return true; 
        }

        if(node.leftChild != null) {
            searchNum(node.leftChild, num);
        }

       if(node.rightChild != null) {
            searchNum(node.rightChild, num);
        } 

       return false;
    }
}

I am trying to find if a given number equals the sum of any 2 numbers in a binary search tree. I know where the error is, but I don't know how to correct it.

The folliwing lines

if(find(result)) {

return true; 

}

should terminate the method because once I've got a true, that's all I need and I should return the value to the calling function. However, the recursion continues to execute finally returning the value from the last recursive call. Please help.

public boolean searchNum(BinTreeNode node, int num) {
    if(node == null) {
        return false;
    }
    else {
        if(node.leftChild != null) {
            searchNum(node.leftChild, num);
        }
        int result = num - node.item;
        System.out.println(node.item);
        //I have a separate find() which finds if the key is in the tree
        if(find(result)) {
            return true; 
        }

       if(node.rightChild != null) {
            searchNum(node.rightChild, num);
        } 

       return false;
    }
}
}
Prasanna
  • 85
  • 1
  • 2
  • 10
  • So you've given some code, with part of it being another key function. It needs the find piece of code probably – Ben Hack Sep 19 '13 at 16:07
  • You are doing nothing with searchNum. You need to return the keep returning the value of searchNum up the stack or you just lose that true. Right now in a non-terminal case the only possible return value you have is false. – MirroredFate Sep 19 '13 at 16:11
  • How do I pass that true up the recursion tree? I am lost :( – Prasanna Sep 19 '13 at 16:22
  • See my answer. You just return the value. And recursion isn't really a tree, it's a stack. – MirroredFate Sep 19 '13 at 16:53

2 Answers2

1

Try moving your find check before you recursively check the left side of the tree. Otherwise you will go down the left side of every node before you even check the node itself.

else {
    // Moved to the top of the else
    int result = num - node.item;
    System.out.println(node.item);
    if(find(result)) {
        return true; 
    }
    // Then check recursively
    if(node.leftChild != null) {
        searchNum(node.leftChild, num);
    }
    if(node.rightChild != null) {
        searchNum(node.rightChild, num);
    } 

   return false;
}
rgettman
  • 167,281
  • 27
  • 248
  • 326
  • Oh, OK! I just wrote the code for in-order traversal of the tree. So, should I write pre-order traversal then? – Prasanna Sep 19 '13 at 16:16
  • Yes. You want to stop when you find what you're looking for, so why search further? – rgettman Sep 19 '13 at 16:17
  • I just moved my find, but it still doesn't work :( How do I paste my code again? I am only able to "comment" and not "post" a reply. – Prasanna Sep 19 '13 at 16:20
1

The most general recursive formula is as follows:

function sampleRecursion(a){
    if(isTerminalCase) {
        return true;
    }
    else {
       a = modify(a);
       return sampleRecursion(a);
    }
}

Using that as a template for your code, you should have something like this:

public boolean searchNum(BinTreeNode node, int num) {
    //validate the input
    if(node == null) {
        return false;
    }
    //this is your terminal case
    int result = num - node.item;
    //I have a separate find() which finds if the key is in the tree
    if(find(result)) {
        return true; 
    }
    //this if doesn't make any sense as you validate this input already
    //if(node.leftChild != null) {
    //    searchNum(node.leftChild, num);
    //}
    //here is where we are returning the value we get back from searchNum
    return seachNum(node.leftChild, num) || searchNum(node.rightChilde, num);
    //System.out.println(node.item);
    //I moved this up into the single return case, so everything after this is unnecessary
    //if(node.rightChild != null) {
    //    searchNum(node.rightChild, num);
    //} 
    //return false;
}

So, cleaned up, that should look like:

public boolean searchNum(BinTreeNode node, int num) {
    //validate the input
    if(node == null) {
        return false;
    }
    //this is your terminal case
    int result = num - node.item;
    //I have a separate find() which finds if the key is in the tree
    if(find(result)) {
        return true; 
    }
    //here is where we are returning the value we get back from searchNum
    return seachNum(node.leftChild, num) || searchNum(node.rightChilde, num);
}

This is an approximation of what your recursive function should look like. I don't know what the find function does, so I don't know if it will to what you want.

Furthermore, from your description you are trying to use two numbers in the search tree, not one. In the code you have now, you are only using one. So if you pass in, say, ({a node}, 15), you will get... something. If your find function calls searchNum({top node}, result), you will be ok, I think. But I have no idea what find does so I can't say for sure.

EDIT: It might be simpler to consolidate find and findHelper.

private boolean find(int key, BinTreeNode node) {
    if (node == null) {
        return false;
    }    
    if(key == node.item) {
        return true;
    }
    else if(key < node.item) {
        return findHelper(key,node.leftChild);
    }
    else {
        return findHelper(key,node.rightChild);
    }
}

Then just call it in searchNum with find(result, root). That is, if you have access to root in searchNum.

MirroredFate
  • 10,877
  • 12
  • 60
  • 91
  • Thank you very much. I don't understand that comment though. Why does that block not make sense? – Prasanna Sep 19 '13 at 17:39
  • At the beginning of the function you say `if(node == null)`. There is no reason, then, to say `if(node.leftChild != null)` before passing in that value, because you are already checking for null at the very beginning of `searchNum` – MirroredFate Sep 19 '13 at 17:49
  • Oh, I see. So my mistake was omitting the "return" before "searchNum(this.leftChild)" . I'm not able to understand how it has made my code to work now! Please help me understand it. By the way, I've edited my original post to include my find(). Please take a look. – Prasanna Sep 19 '13 at 17:51
  • Will I not get a NullPointerException if I don't check for null and if this.leftChild turns out to null? I am checking at the beginning, but won't I get an exception in this place? – Prasanna Sep 19 '13 at 17:54
  • You will only get a null pointer exception if you attempt to do something with the null (any attempt to dereference it). As long as you check before you dereference the pointer, you will be fine. http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception So even if `node.leftChild` is null you are fine, because when you pass it in, you will see that it is null and return false. – MirroredFate Sep 19 '13 at 18:23
  • Thank you very much. Yes, everything works now. I've not tried consolidating find() yet, but the code works. I am still not understading one part of your answer: how placing "return" before "searchNum(this.leftchild, num) magically gives the right answer. What was happening earlier when I didn't have that "return" keyword? – Prasanna Sep 19 '13 at 18:36
  • Before you were evaluating a specific node, but not doing anything with the evaluation. It was the same as saying: `public int add(int a, int b){ a+b; return 0;}` In that case, you add `a` and `b` together, but you don't store the result anywhere or return it, you just `return 0` every time. That is what you were doing. http://www.tutorialspoint.com/java/java_methods.htm – MirroredFate Sep 19 '13 at 19:40
  • Finally, this algorithm takes O(n log n) time if I am not mistaken. There are n elements in the tree and each find takes O(log n). Is there a better way of implemeting this problem? Not necessarily only running time-wise, but in general also. – Prasanna Sep 19 '13 at 19:49
  • There are ways to make it more efficient, but that is beyond the scope of this question. – MirroredFate Sep 19 '13 at 20:35
  • Oh ok..sorry I thought it would be easier here. Should I start a new thread for this question? – Prasanna Sep 19 '13 at 20:51