How Do You Make A Recursive Boolean Method Of "isSubstring(str1, str2)" - java

if (isSubstring(str1, str2))
System.out.println(str1 + " is a substring of " + str2 + ".")
and here is the method for isSubstring:
public static boolean isSubstring(String str, String target)
{
if (str == target)
return true;
return (isSubstring(str, target.substring(0,5)));
}
That is what I have in code right now and I can't fathom how you would go about solving this. My instructor is requiring us to use recursion so the return MUST call itself. Normally this problem could EASILY be done with only one line of code:
public static boolean isSubstring(String str, String target)
{
return str.contains(target)
}
But I must pointlessly use recursion to solve this and it is EXTREMELY frustrating knowing how trivial this method is and how overly complicated my instructor is forcing us to do this. I don't really know where to start because "return str.contains(target)" doesn't give me a good foundation for how I could try solving this.

A couple things:
First, you have the right idea, but you want to make the 'next' string you search one size smaller than your current string. So if you were looking in the string Hamburger, you'd search amburger second, then mburger. So when you recur, you might try something like return isSubstring(str,target.substring(1)) Right now you appear to be using the number 5 as to take the first 5 characters. That's strange because the first time you do it, (Hamburger to Hambu) you won't ever be able to do it again. And if your original target was "ham" then you'd bomb immediately! Not so good.
Second, it's not enough to test if it's equal. Using the hamburger example, if you were looking for urge, you'd find urger and then go right to rger. You wouldn't ever get urge. So instead of testing for equals, test with beginsWith() instead. (If you were shrinking it from the back, like Hamburger to Hamburge to Hamburg, then you'd use endsWith().)
Lastly, you don't have a good path for what to do if you don't reach the goal. If you have xyzzy for a target, and you're searching for bob, you won't find it. So you need a "base case", which I recommend using as the first line. Something that says "if it would be impossible for the token to be in the target, then let's return false right away".
It's hard and its frustrating, and it seems pointless. But keep in mind he's not trying to teach you to search strings. That's silly, you know how to search strings! He's trying to teach you recursion, which is not easy to "get".

One fix is: Use equals() instead of == while comparing String/Objects. == compares reference equality. equals() compares for content equality.
if (str == target)
should be
if (str.equals(target))

Okay I got it, Asad's advice was useful. Here is a working method for isSubstring:
public static boolean isSubstring(String str, String target)
{
if (target.length() == 0)
return false;
if (str.equals(target))
return true;
else
return (isSubstring(str, target.substring(0,target.length()-1)));
}
I'm not sure if the second "if" should be an "else if" instead.

Compare strings with the equals() method: change
if (str == target)
to
if (str.equals(target))

You know that the function applied to:
base case) An empty string, must return false;
base case) A string starting with the once you are looking for, must return true;
rec case) Else remove the first character and check the rest of the string.
Here the code in Java:
public static boolean isSubstring(final String str1, final String str2) {
if ((str1 == null) || (str2 == null) || str1.isEmpty()) {
return false;
} else if (str1.startsWith(str2)) {
return true;
} else {
return isSubstring(str1.substring(1), str2);
}
}
Test:
public static void main(final String[] args) {
System.out.println(isSubstring("hello this is a simple test", "is a"));
}
Output:
true

Related

Implementing an equals method recursively

Basically, I need to compare two arrays and check if they have the same values in the same positions (recursively of course). I get an error with my current code: Array out of index exception:20
The code I have right now looks as follows:
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd){
if (first[iStart] == second[iStart]){
if (equalsHelper(first,second,(iStart+1),iEnd))
{
return true;
}
}
if (iStart == iEnd){
return first[iEnd] == second[iEnd];
}
return false;
}
You simply need to put you stop condition at the begin of you code. This will work if iStart is 0 at the beginning and iEnd is array length - 1.
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) { // you need to check this first
return first[iEnd] == second[iEnd];
}
if (first[iStart] == second[iStart]) {
if (equalsHelper(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
If you want to use the array length as input for iEnd you just need to change the code a little
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) {
return true;
}
if (first[iStart] == second[iStart]) {
if (equalsHelper2(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
Since performance was mentioned a few times I will say a few things about it.
The stack contains information about local variables and function calls. So each recursiv call will save these informations on the stack which will lead to a stackoverflow on huge inputs since the stack only has limited space. It is also slower in terms of execution due to more assembler commands in comparison to loops.
This can be avoided by using tail recursive functions.
A tail recursive call means simply that your recursive call must be the last statement that is executed in your method. The compiler will translate this into a loop. This is faster and uses less space on the stack.
A tail recursive version of your equals method would look like this:
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd)
{
if (iStart == iEnd)
{
return true;
}else{
if(first[iStart] != second[iStart])
{
return false;
} else
{
return equalsHelper2(first, second, iStart + 1, iEnd);
}
}
}
Leaving aside the question of whether recursion is the right solution (it really isn't, iteration here is trivial and will perform better), the problem is that the termination condition (iStart == iEnd) is not checked until after the recursive call.
Any recursive algorithm must a) check whether it is appropriate to continue recursing, and b) do the recursive call after that check. Failing to include the first step, or doing the steps out of order, will result in infinite recursion until an error is reached (StackOverflowError if nothing else happens first).
You do have a condition check before your recursive call, but it's for the method's overall purpose rather than for ending recursion. You also have a condition check for ending recursion, but it's done after the recursive call. The solution is to swap their order - take the if (iStart == iEnd) block and move it to before the if (first[iStart] == second[iStart]) block.
Recursion is a powerful programming technique, but has some draw backs in the Java language. If a method in java calls itself recursively an excessive number of times before returning it will lead to a StackOverflowError. It this instance, comparing equality of two Array's is almost guaranteed to do so.
Other languages like Scala allow you to write recursive functions which are optimised for recursion (tail recursive) and execute in constant stack space.
That been said, you should think whether recursion is really the correct solution here. It neither optimises the solution, nor adds code clarity.
Note: If you just want to compare two Array's in Java, then java.util.Arrays already has you covered.

Converting A String to a Boolean -- Java

I've been searching around stackoverflow, and I've found a few other questions on converting a string to a boolean, but I can't make it work. Perhaps it is just the way I am trying to use it is incorrect.
Anyways, I am trying to convert two different input strings "M" or "I" in to boolean for use in an if statement. What is basically want the functionality to be is this:
// the text that is retrieved is assumed to be either"M" or "I"
M=Input.getText
I=Input.getText
If M shows the value "M",
do stuff here
else if I shows the value "I",
do stuff here
else if neither above are true,
throw an exception here
I've tried any number of "toBoolean"s and "Boolean.valueof"s, but none of what I try is working.
PS, Sorry for not having actual code to work with, this is my first step, and thus I haven't built anything up around this piece.
You can use String's methods to check for whether it contains a given literal value, equals it, or equals ignoring case.
A draft condition would be:
if ("myValue".equalsIgnoreCase(myText)) {
// TODO
}
else if ("myOtherValue".equalsIgnoreCase(myOtherText)) {
// TODO
}
else {
// TODO
}
Here is the documentation in java.lang.String:
equals
equalsIgnorecase
contains
You also want to check the many other methods, such as startsWith, endswith, etc. etc.
Use this for one boolean:
boolean b = (M.equals("M") || I.equals("I"));
Or this for two boolean:
boolean booleanM = (M.equals("M"));
boolean booleanI = (I.equals("I"));
if(booleanM){
//do stuff here
}else if(booleanI){
//do stuff here
}else{
//do stuff here where both are false
}
This is the faster way if you need to verify more than one time, only one time use this:
if(M.equals("M")){
//do stuff here
}else if(I.equals("I")){
//do stuff here
}else{
//do stuff here where both are false
}
You can simply use boolean b = Input.getText().equalsIgnoreCase("YourTrueString"). This method will detect if the input text is exactly the same as "YourTrueString". If not, it'll return false. This way anything that isn't true becomes false.
From your pseudo code
// the text that is retrieved is assumed to be either"M" or "I"
M=Input.getText
I=Input.getText
If M shows the value "M",
do stuff here
else if I shows the value "I",
do stuff here
else if neither above are true,
throw an exception here
To Java
// In its own method for reuse, in case you want to extend character support
public boolean match(String character, String match) {
return character.equals(match);
}
You can then invoke this simple method
String m = Input.getText();
String i = Input.getText();
if (match(m, "M")) {
do stuff here
} else if (match(i, "I")) {
do stuff here
} else {
throw an exception here
}

How to write (if, if, if) else if none

I'm trying to make a group of if statements, in which each if will print given some argument is true, but an else that will only print if none of the ifs were returned. I don't think an else if would work in this case.
I have some code (the colors are just as examples):
boolean any=false;
if(redStage==2)
{ any=true; System.out.print(redComplete); }
if(blueStage==2)
{ any=true; System.out.print(blueComplete); }
if(greenStage==2)
{ any=true; System.out.print(greenComplete); }
if(any==false)
System.out.print(noneComplete);
Is there anything I can do to eliminate the need for a separate boolean to check whether any of the if's arguments were true?
Edit:
(I just noticed what may be confusing. The code im using isn't actually using return. Instead, it is printing out the results, which means more than one thing can be returned.)
Since you need to processes the stages independently from one another, and more than one can be complete at the same time, your code is as good as it can be.
What follows is my answer to your original question:
You don't need the boolean. Your code is equivalent to:
if (redStage == 2) { return redComplete; }
if (blueStage == 2) { return blueComplete; }
if (greenStage == 2) { return greenComplete; }
return noneComplete;
This makes use of the fact that each if body contains an unconditional return. If this wasn't the case, you could phrase the construct like so:
if (redStage == 2) {
// redComplete
} else if (blueStage == 2) {
// blueComplete
} else if (greenStage == 2) {
// greenComplete
} else {
// noneComplete
}

String array[0] don't pass at the if

Hello everybody I have a question:
I have a array
String[] parte
and I need of the first value of the array so I did:
String verifica = parte[0] // It can be N (for Name) L (for List) and E (for Error)
Why if I run this code and I know that "verifica" is L
if (verifica == "L") { //If code
} else { //Else code
}
it returned to me always the Else code
ThankYou sooooo much
-Matteo
Comparing Strings in Java must be done with String.equals():
if (verifica.equals("L")) { //If code
What you were trying to do was comparing two distinct objects, and not their contents.
You need to use:
if (verifica.equals("L")) { //If code
} else { //Else code
}
instead of '=='. '==' in Java checks for object identity in memory, where the functionality you're needing here is to compare String values. Took me experiencing this error to realize the difference (I come from a C# background) in Java as well.
Use the equals operator for strings:
if (verifica.equals("L"))
You want if (verifica.equals("L")) or if (verifica.compareTo("L") == 0). == is not a reliable operator for comparing strings.

Java recursive binary tree

Welcome!
I have a recursive public static method named less that takes a tree node (an original binary tree, not really a search tree) and a int parameter that returns if all the values in the tree are less than the integer. So, I would use a public class TN { public int value; public TN left, right; public TN(int v, TN l, TN r) {value = v; left = l; right = r;} }
So, my method would look like this:
public static boolean less(TN s, int toFind){
if (s == null)
return true;
else{
if(s.value <= toFind)
return less(s.left, toFind) && less(s.right, toFind); // right here do I return true? or do I have to somehow recall recursively
else
return false;
}
I was wondering if that was right or am I missing something??? Do I have to return true and false??
There are much more elegant, OO ways to write this. My recommendation would be to make less() a non-static member function of the TN class. That way, if the tree's root node is called root, you just call root.less(). Each call to less() will then call left.less() and right.less().
Since you posted example code that wouldn't even compile, I'm wondering if you're using an IDE, or even tried to compile your class using javac. I strongly recommend getting Eclipse, Netbeans, or another IDE if you're new to Java.
return less(s, toFind);
should be:
return less(s.left, toFind) && less(s.right, toFind);
I don't know why the function is static.
As mentioned before, your first part should just be:
if (s == null) return true;
(EDIT: This will let you get a true result when all nodes meet the condition. You have an == in there that should be a <).
EDIT: Ok, you've got a lot of problems than just those I mentioned. You need to logically step through your code.
You need to traverse your tree, so you'll need to call your function on your children nodes. Next, you need to return true as your default result. That way, when you reach a number greater than what you're looking for, you can return false immediately without traversing any of the children. I hope I've helped you enough with the logic for you to get through the rest of it yourself.
First, if (s = null) should be if (s == null) as you are doing a comparison, not setting the value of s to null.
The statement return less(null, toFind); keeps calling your method - you'll overflow your stack.
Notice how there's no way that your function could ever return true because every time you terminate the recursion, you're returning false? And the problem is in your first check. You say that "all the values in the tree are less than the integer." Well, in an empty tree, all the values (of which there are none) are indeed less than any integer, so you should return true in that case.
Also, while you say "less than", you're comparing for equality, so you're actually checking whether all the values are equal to the integer, not less than it.

Categories