adding return case to recursive function - java

When it comes to recursion, here is where I struggle, I know the edge case for when the function should be true, but because I have to add a return false statement as well, and somewhere deep in the call stack, it does become true(which is the whole point of examining!), I want the final outcome to be true, and for the recursion to stop. But eventually, it finds its way to the return false, simply because its the last thing the function does.
public boolean isPathHelper(Node node, String input){
if(node.accept == true){
return true;
}else{
if(input.length() == 0){
return false;
}
isPathHelper(getNextState(node, input.charAt(0) -'0'), input.substring(1));
return false;
}
How do I deal with this scenario? I know global variables can help, but I was hoping there's a gap in my knowledge instead.

Try this:
public boolean isPathHelper(Node node, String input, int count){
if(input.length() == 0){
return false; //I can't go any further: return "failed"
}
else if(count == input.length()){
return true; //if I ever reach here, then I am done: return "success"
}
// else call self recursively
return isPathHelper(
getNextState(node, input.charAt(0) -'0'), input.substring(1), count+1);
}
Just examine your logic and your data carefully enough to be SURE you hit "count == input.length()" at some point. Preferably at some point before you run out of stack ;)

Related

Recursive Statement not Instantly Returning

I am creating a method that takes a list of numbers and an index.
If there is a number after the index that is six times the first number, it returns true. Otherwise, it returns false.
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
firstElementMultiple(Numbers, index+1);
return false;
With a list of {5,6,7,30} and an index of 1, false is returned, even though 30 is in the list.
6
7
30
Yep
Is printed, which shows me that it did recognise that 30 was in the list. However, it is still returning false even though the next statement is true and should stop the method?
This has to be done by recursion.
edit: I have to put the 'return false;' at the end as, without it, it doesn't let me. However, I don't see how it can ever get there because there is always a recursive call in the way.
firstElementMultiple(Numbers, index+1);
return false;
Here's the end of your method. This is what it does. It says "Call firstElementMultiple to keep looking for the value we're looking for. Once you've finished looking, completely ignore whether or not you found it and return false anyway."
Given that, how can you fix it to do what you want it to do, namely return whether or not we found the element?
Because in the end, you are returning false in your recursive function no matter what you get in further calculations. You should change your code to this:
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
return firstElementMultiple(Numbers, index+1);
}
Basically you need to change
firstElementMultiple(Numbers, index+1);
return false;
to
return firstElementMultiple(Numbers, index+1);

How do you recurse through two return statements? [JAVA]

I am currently trying to implement a binary search tree shape comparison and am having trouble with one line of my code.
if(treeStructOne.getHeight() == 1 && treeStructTwo.getHeight() == 1) //Base Case, if both are empty then they must be equal!
{
return true;
}
if(treeStructOne.getHeight() != treeStructTwo.getHeight()) //First make sure height is the same, if not, must be unequal
{
return false;
}
if(treeStructOne.hasLeft() && treeStructTwo.hasLeft())
{
return similar(treeStructOne.getLeft(),treeStructTwo.getLeft());
}
if(treeStructOne.hasRight() && treeStructTwo.hasRight()) //PROBLEM IS HERE
{
return similar(treeStructOne.getRight(),treeStructTwo.getRight());
}
return false;
The problem occurs when a node on Tree 1 and 2 has a left child, but only tree 1 has a right and not Tree 2. After it checks that they both have left children, it does not run the the check on right children if left is true. Is this to do with the way recursion works in java?
if both trees hasLeft() returns true then your method will return in that if clause. My guess is you want to assign the result from the similar call in the last two if clauses and after the if clause do something like
return leftSimilar && rightSimilar;
The first two if's will work, but the last part should capture the conditions of p implies q which is ~p or q for both left and right. In other words, if treeStructOne has a left subtree and treeStructTwo has a left subtree, then check to see if they are similar (return similar...)
if(treeStructOne.getHeight() == 1 && treeStructTwo.getHeight() == 1) //Base Case, if both are empty then they must be equal!
{
return true;
}
if(treeStructOne.getHeight() != treeStructTwo.getHeight()) //First make sure height is the same, if not, must be unequal
{
return false;
}
return (treeStructOne.hasLeft() && treeStructTwo.hasLeft()
? similar(treeStructOne.getLeft(),treeStructTwo.getLeft())
: false)
&& (treeStructOne.hasRight() && treeStructTwo.hasRight()
? similar(treeStructOne.getRight(),treeStructTwo.getRight())
: false);
The return statement immediately returns from the current method, i.e. the remainder of the method will not be executed.
In your case, you want to make two recursive calls before returning from the method. You can do this with:
boolean similarLeft;
if(treeStructOne.hasLeft() && treeStructTwo.hasLeft()) {
similarLeft = similar(treeStructOne.getLeft(),treeStructTwo.getLeft());
} else {
similarLeft = ?; // TODO what is good condition here?
}
then do the same for the right side and conclude with
return similarLeft && similarRight;
However, for truly ideomatic java, I'd do the null checks after invoking the method rather then before it, thereby reducing code duplication:
boolean similar(TreeStruct x, TreeStruct y) {
if (x == null) {
return y == null;
} else {
return y != null && similar(x.left, y.left) && similar(x.right, y.right);
}
}

how to use return keyword in a find operation in binary search tree

This is my method to find if a particular node is there in a binary tree.Here's my method and it works fine.
public boolean find(BinaryNode p,int x){
if(p==null){
return false ;
}
else{
if(x==p.element){
return true;
}
else if(x<p.element){
return find(p.left,x);
}
else {
return find(p.right,x);
}
}
}
My question is if I don't insert return keyword inside else if(x<p.element){ and else { I get an error as missing return statement.
Say I have a binary tree consisting of elements 5,4,6,60,25,10 .
So if i am searching for 10 there's a time that
if(x==p.element){
return true;
is satisfied because of recursive calls.Then there's a return statement to be found.
If i am searching for an element that's not in tree eventually I would reach the statement
if(p==null){
return false ;
},there we find a return statement.
Therefore even I don't have the return in else if and else clauses somehow there's a way that I finally reach a return statement right?So what's wrong with not having return keyword in else if and else clauses.
Why do I have to have it there?
Why can't I do it as
`public boolean find(BinaryNode p,int x){
if(p==null){
return false ;
}
else{
if(x==p.element){
return true;
}
else if(x<p.element){
find(p.left,x);
}
else {
find(p.right,x);
}
}
}`
The closest to the way you want your if-else if-else clause to behave is using the ? conditional expression:
public boolean find(BinaryNode p,int x)
{
if(p==null) {
return false ;
}
else {
return (x==p.element)?true:(x<p.element?find(p.left,x):find(p.right,x));
}
}
Other option is to store the value to be returned in a local variable and only return it at the end of your method:
public boolean find(BinaryNode p,int x)
{
boolean returnValue = false;
if(p!=null)
{
if(x==p.element){
returnValue = true;
}
else if(x<p.element){
returnValue = find(p.left,x);
}
else {
returnValue = find(p.right,x);
}
}
return returnValue;
}
And my favorite way, using short-circuit evaluation of logical expressions:
public boolean find(BinaryNode p,int x)
{
if(p==null) return false;
return x==p.element || (x<p.element && find(p.left,x)) || find(p.right,x);
}
Since Java's || and && operators won't evaluate their right part expression when the left part already determines their result. If x==p.element is true, then true will be returned without evaluation the rest of the line. If not, then (x<p.element && find(p.left,x)) will be evaluated following the same rule.
Note how find(p.left,x) won't be evaluated when x<p.element is false.
You need return statement because the find-function in the else if - else statement will return to the caller after its done, but the first-call function still have to return a value to the caller
Therefore even I don't have the return in else if and else clauses somehow there's a way that I finally reach a return statement right?
No compiler doesn't know about it. Compiler doesn't know what will be value of x and p at run-time.
Compiler simply checks for all the possibilities of the return statement and there must be exit point of the method.
You need to provide the logic to move either in right direction or left direction of the binary tree.
The last two else-if are not responsible to actually return the result of the find method its used just to move in the right direction of the tree. Ultimately final result of the the find method will come out by first two if-else clause.

Java return statement

Eclipse keeps telling me to add a return statement to the method, even though I did so.
public class PrefixCode {
public String isOne(String[] words) {
if(words.length==1) {
return "Yes";
}
ArrayList<Integer> indexPositions= new ArrayList<Integer>();
for(int i=0;i<words.length;i++) {
String firstWord=words[i];
java.util.List<String> listOfWordsToCheck = new ArrayList<String>(Arrays.asList(words));
listOfWordsToCheck.set(i,null);
for(int j=0;j<listOfWordsToCheck.size();j++) {
String secondWord= listOfWordsToCheck.get(j);
if(firstWord.startsWith(secondWord)==true) {
indexPositions.add(j);
}
else if(firstWord.startsWith(secondWord)==false);
}
}
if(indexPositions.size()==0) {
return "Yes";
}
else if(indexPositions.size()!=0) {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
}
}
}
My return statements are outside of the for loops, so I don't understand what's wrong here.
There is no default return. The only returns you are making are if some conditions are true. What if the conditions are false?
Add a return after the last else block and you are all good to go.
The else block is redundant. What lies inside the else block should be be without else.
Since you have added if, else if, you need to else to that control flow to satisfy the compiler. Logically, size can be either zero or more than zero. So, you need to have if and else part only
if(indexPositions.size()==0){
return "Yes";
} else if(indexPositions.size()!=0){
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
} else {
// return what?
}
You can simplify this logic by,
if(indexPositions.size() == 0) {
return "Yes";
} else { //size more than zero
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0) + "";
}
you should use else instead of
else if(indexPositions.size() != 0) {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0) + "";
}
The compiler doesn't know if the if conditions are going to succeed. So, you need to add a default return out of those if (even if your if conditions cover all possible cases!)
One of the best practice is to have only one return at the method end! Like this:
public String isOne(String[] words) {
String isOne = null;
if(words.length==1){
isOne = "Yes";
}
...
if(indexPositions.size()==0){
isOne = "Yes";
}
else if(indexPositions.size()!=0){
Collections.sort(indexPositions);
isOne = "No,"+indexPositions.get(0)+"";
}
return isOne;
}
Sometimes you may initialize the variable with a default value too, even if in this case is not needed :
String isOne = "No";
In also in your code there is an "error", the indexPositions.size may only be 0 or more, so you may want to use else instead of else if, and complete the graph. In this case eclipse won't tell you to add a return statement anymore, even if you use the return inside the condition block.
if(indexPositions.size()==0) {
return "Yes";
}
else {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
}
I usually do this by declaring a boolean at the start of the function and set it to false. If for whatever reason the function says that variable is gonna be true. I set the declared variable to true instead of returning true. At the end of the function i return that declared variable.
It then has its default return and if the variable was set to true, it returns true.

Error with return in Java?

I get an error in the code from this part of my code:
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
}
return true;
}
When I remove the first return true and instead to the last return true, it don't get the error in my eclipse code, but why can't I have the first place and would this be the same? Thanks!
EDIT: The error message from eclipse say: This method must return a result of type boolean. I'm confused because isn't that what I have done?!
Yes, a break must be in the code
Can I write the method in some other way?
EDIT NUMBER 2
Why isn't this code working?
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
}
This method returns a boolean value so I don't understand why I get an error!? The code looks right to me?
Your edit #2 doesn't compile because there is a possibility that your code won't enter the for-loop. This will be the case if customerList.size() is 0. To fix this, you'll simply need to add a return statement after the for-loop as well:
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
return false;
Another point here is that this code doesn't logically make much sense: it will only return true or false based on the first item in your list. And this is probably not what you want. So take a closer look at several of the other answer here, many of which are good examples for how you can do this.
public boolean findCustomer(String inPersonalNumber){
boolean result = false;
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
result = true;
break;
}
}
return result ;
}
When I remove the first return true and instead to the last return
true, it don't get the error in my eclipse code, but why can't I have
the first place and would this be the same?
If you remove the second return statement the code would be able to run and not return a value - this is not possible as you defined the method to have a return type of Boolean. So it must always return a value no matter what.
Just change the second return statement to false, should do what you want.
Looks like you have turned off the Build Automatically feature of eclipse. It maybe complaining about an error that used to be present when you still hadn't typed in your code fully! This can also happen if you have back-dated your system for some reason.
Also, shouldn't you be returning false if the condition doesn't satisfy?
public boolean findCustomer(String inPersonalNumber) {
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)) {
return true;
}
}
return false;
}
First return will return only in case of all conditions satisfied, but this method should be returning boolean as per code. It would be expecting a return in failure case also.
Removing first return won't affect compilation as it has a return in second place which will work without any condtions.
Edit : Answer for your second question
This code has two return's, but what if your customerList is size 0, in that case also, method must return boolean. right? for that only, compiler is asking.
BTW, code doesn't have null checks.
Your final code could be this. Keeping multiple return statements in code in not a good practice.
public boolean findCustomer(String inPersonalNumber) {
boolean retVal = false;
if (!(inPersonalNumber == null || inPersonalNumber.trim().equals("")
|| customerList == null || customerList.size() == 0)) { // inputs are valid to run this check
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (inPersonalNumber.equals(customerList.get(i).getCustomerPersonalNumber()) { // to avoid NPE, kept inPersonalNumber in check
retVal = true;
break;
}
}
}
return retVal;
}
Because your for loop looses meaning if you're returning true anyway.
If you want to stop loop use break; instead of first return.

Categories