Java string recursion - java

I am trying to learn Java, and now I'm trying algorithms. So, I'm stucked on recursion. I have a code that I don't understand.
public static String reverseString(String text){
// base case
if (text.length() == 0) {
return text;
}
else {
// recursive call
return reverseString(text.substring(1)) + text.charAt(0);
}
}
public static void main(String[] args) {
String str = new String("howdy");
// calling recursive function
String reverse = reverseString(str);
System.out.println(reverse); // Prints: ydwoh
}
Problem is that for me recursive call in this code for me is:
for the first time it retuns owdyh,
second time wdyo and so on.
I can't understand how the string ydwoh borns. I suspect that somewhere chars concotanating in the right order, and stored somewhere, but where is this place I also don't know.
UPDATE
I tried it with paper, what I got:
first recursive call:
return value owdyh = "owdy" + "h"
second call:
return value wdyo = "wdy" + "o"
and so on

The difficulty is the processing after the call. The first letter is added to the end of the result of reverseString of the rest.
reverseString "howdy"
reverseString "owdy"
reverseString "wdy"
reverseString "dy"
reverseString "y"
reverseString ""
return ""
return "" + "y"
returns "y" + "d"
returns "yd" + "w"
returns "ydw" + "o"
returns "ydwo" + "h"
returns "ydwoh"
It is like a mathematical proof by induction:
The empty string is reversed (result empty string).
When the recursive call works on a smaller string,
placing the first char at the end, also reverses the string.
So reverseString works for all length of strings.

Thanks for the answers! They helped me to figure out my misunderstanding!
What I couldn't understand is where all the chars from the text.charAt(0) are stored! The trick is that they are stored in the stack without any links. It's LIFO(Last-In-First-Out) approach in work.

Related

Shift a number to the beginning of a string recursive Java

The task is to shift a number within a string to the beginning of the string with a recursion. So if I feed "ba3nana" to the code it should return "3banana". Did some recursive tasks already but this one I am stuck on.
I tried I guess already 50 different combinations but so far my code only returns "banana3" so I go the opposite way with my number. Does anyone see the mistake in my code?
The call of the method looks like this:
System.out.println(shiftDigitLeft("ba3nana"));
This is the code so far:
private static String shiftDigitLeft(String text) {
if (text.isEmpty()) {
return text;
} else {
if (text.charAt(0) >= '\u0030' && text.charAt(0) <= '\u0039') {
return shiftDigitLeft(text.substring(1)) + text.charAt(0);
} else {
return text.charAt(0) + shiftDigitLeft(text.substring(1));
}
}
}
Thanks in advance!
The pseudocode for what you've written would look like this
String shiftDigitLeft(String text) {
if the text is empty
return empty
else
if the first character is a digit
return shiftDigitLeft(the rest of the string) + the digit
else
return the letter + shiftDigitLeft(the rest of the string)
}
It should be obvious from this that digits never get moved to the left, only to the right.
You should probably invert your approach so that you look whether the last character is a digit, and if it is then move it to the beginning.

Could someone please explain the algorithm of reverse string using tail recursion?

I am sorry for being stupid to ask this question. I able to understand the code until getting the last character of the given string and return, then I am not able to relate the recursion logic.
Before posting it here, debugger helped me partially. Unfortunately, not 100%
Could you please help me to understand this?
public static void main(String[] args) {
System.out.println(reverseRecursively("abcd"));
}
public static String reverseRecursively(String str) {
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) + str.charAt(0);
}
Debugger Output:
0=abcd
1=bcd
2=cd
3=d
Final: dcba
Well, it's a pretty simple logic:
return reverseRecursively(str.substring(1)) + str.charAt(0);
If you put a System.out.println() before the return, you'll get the following output:
Recursing with substring: bcd and adding a
Recursing with substring: cd and adding b
Recursing with substring: d and adding c
Adding d as final char
If you reverse this, you get dcba.
Why is it reversed though?
Well, you have to think of the call trace:
return reverseRecursively("bcd") + a -> retruns "dcba"
-> return reverseRecursively("cd") + b -> returns "dcb"
-> return reverseRecursively("d") + c -> returns "dc"
-> return d -> returns "d"
I guess the key point is to understand that the recursion is always combined with the result of another recursion.
When the method runs, it will check first if the String is one or zero characters in length. This will tell it whether it is the final character in the string. If not, it will append the current character to the end of the string and run again, this time on the next character along. This means that the string gets a character shorter every time.
What may be confusing is that the str.charAt(0) is not passed into the next iteration of the method, rather just added as a part of the return statement. This means that once the method has completed the final character, it will return all characters in backwards order as each method completes one after the other starting with the one that returns the last character. This will happen until all methods return and returns your reversed string.
It's like layers of methods, one will invoke another and then they will all complete in backwards order to the order in which they were called.
Hope this helped your understanding!
No question is stupid question. If one doesn't ask a question, thinking that people will think he/she is stupid, then he/she is stupid for life. :)
Now the explanation:
I added a print statement to help you with it.
public static String reverseRecursively(String str) {
System.out.println("For debuging : "+str); // this is my print statement.
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) + str.charAt(0);
}
It prints the below.
For debuging : abcd
For debuging : bcd
For debuging : cd
For debuging : d
dcba
The base criteria for the method to return the value is, str.length() < 2.
So when the "d" is returned by last method call(or we can say the fourth method call to reverseRecursively(String str)), because the length is less than 2. The third method call will return
"d" + "cd".charAt(0);
which is nothing but : dc.
Similary 2nd method will use the third method's return value (dc) and return the value
"dc" + "bcd".charAt(0);
which is dcb.
and so the first method call, where you passed the string "abcd" as input will return.
"dcb" + "abcd".charAt(0);
which is dcba.
Hope this helps. Cheers !!!
`public static String reverseRecursively(String str) {
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) //take "bcd" : 1st Itration
//"cd" : 2nd
// "d" : 3rd (this makes str.length() < 2)
// 3rd returns first with "d" and pass control back to 2nd recursion
//2nd takes d and adds 0th char c and returns with "dc" and pass control to 1st
//1st takes dc and adds b returns with "dcb" and pass control to base call
// base call take "dcb" and adds 0th char a and returns to calling method
+ str.charAt(0);
}`.

Method to check if a Char is present on a specific String

I need to write a program where the main reads two strings as input: if the strings have the same length, then it has to pass the whole first string and the first char of the second string to a method called find, which has to return 'true' if the character appears even a single time on the string. If the length differs, then it will pass the whole second sentence and the last char of the first string to find. At last, the main will give whatever the method returns as output, so it has to be true, or false. I've created the whole main, and it works correctly, but I have no idea how to create the find method. Here is the code:
import java.util.Scanner;
public class Exercise {
/*
* public static boolean find(String... sentence, char... character) {
* // No, I can't use multiple varargs...
* }
*/
public static void main(String[] args) {
String first, second;
char firstChar, lastChar;
Scanner keyboard = new Scanner(System.in);
int lengthFirst, lengthSecond;
boolean goal = true;
first = keyboard.nextLine();
lengthFirst = first.length();
lastChar = first.charAt(lengthFirst - 1);
second = keyboard.nextLine();
lengthSecond = second.length();
firstChar = second.charAt(0);
System.out.println("Length 1: " + lengthFirst); // Those lines are test lines.
System.out.println("Length 2: " + lengthSecond); // They're here just to check
System.out.println("Char 1: " + firstChar); // if everything else works.
System.out.println("Char 2: " + lastChar);
if (lengthFirst == lengthSecond) {
goal = find(first, firstChar);
System.out.println("Goal is: " + goal);
System.exit(0);
} else
goal = find(second, lastChar);
System.out.println("Goal is: " + goal);
System.exit(0);
}
}
I was thinking about using the varargs option, using a varargs for the String, and another for the char, and then using a 'for' loop inside of the method to check if the character appears or not, and everything was easy on my head...but with some research I found out it will be a waste of time, because I can't use two varargs on the same method. The for loop idea works, but I can't figure out how to pass only the right String and the right Char. How should I pass them to the method, without passing them both?
Edit: No, this is not a duplicate. I allow loops, the other question doesn't. Also, my problem is about how am I supposed to pass multiple variables, but then using just some. That's an example:
The strings are both long 50, so the method needs to use only 'first' as String, and 'firstChar' as Char.
You can use String.indexOf().
returns the index within this string of the first occurrence of the
specified character. If a character with value ch occurs in the
character sequence represented by this String object, then the index
(in Unicode code units) of the first such occurrence is returned, if
no such character occurs in this string, then -1 is returned.
public static boolean find(String str, char ch){
if(str.indexOf(ch) == -1)
return false;
return true;
}
As you are thinking, you don't need four parameters for this function. You can use this function with two parameters for both cases:
goal = find(first, firstChar);
goal = find(second, lastChar);
EDIT I think you have misunderstood the way the parameters are mapped.
if you have a function like
public static boolean find(String str, char ch){
//do something
}
You don't need to call the find with same parameters str and ch, I mean find(str,ch). You can call them with any parameter, with any name, like :
goal = find(s,c); // s is a string and c is a char
goal = find(a,b); // a is a string and b is a char
when you call find(s,c), s will be mapped to the first argument in your function that is str and c will be mapped to your second argument that is ch.
This is the reason you are able to call both find(first, firstChar) and find(second, lastChar) with a single function.
private static boolean find(String str, char Char) {
for(int i=0;i<str.length();i++)
if(str.charAt(i)==Char)
return true;
return false;
}
This would help hopefully...
Seems like what you are looking for is:
if (second.indexOf(c) == -1) return false; //char c not found
return true;
Find will simply contain
private boolean find(String subject, char first) {
return subject.indexOf(first) > -1;
}

java: code keeps looping

The below code is giving me a headache: It's supposed to jump out of the do--while loop after replacing all \n's, but it doesn't. Any ideas how to solve this?
public String invoerenTemplate(){
String templateGescheiden = null;
String teHerkennenTemplate = Input.readLine();
String uitvoer = teHerkennenTemplate;
do {
templateGescheiden = teHerkennenTemplate.substring(0, teHerkennenTemplate.indexOf(" "));
templateGescheiden += " ";
if (templateGescheiden.charAt(0) == '\\' && templateGescheiden.charAt(1) == 'n') {
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
}
teHerkennenTemplate = teHerkennenTemplate.substring(teHerkennenTemplate.indexOf(" "));
System.out.println(uitvoer);
} while (teHerkennenTemplate.length() > 0);
return uitvoer;
}
EDIT:
I now placed this line: teHerkennenTemplate.trim(); just beneath my if-statement, but now it gives me a StringIndexOutOfRange: 0 error at my first line of my if-statement
I have noticed a couple of problems with the above code, although it is difficult to tell why you are taking the approach that you are to the solution.
The main thing I noticed is that your replace statements do NOT remove the \n characters
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
From Java Documentation:
replace(char oldChar, char newChar):
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
So, you are replacing your string templateGescheiden with \n each time you loop.
Another issue would be the improper shortening of your teHerkennenTemplate string each loop, which is causing it not to terminate correctly. It will always shorten from the next space character to the end of the string (inclusive) - meaning it will never be an empty string, but will always have a " ".
My advice would be to debug and go step-by-step to see where the shortening and string manipulation is not doing what you want, then evaluate why and modify the code appropriately
There's a variety of things wrong with the code:
the index of a carriage return is found in the string with indexOf("\n").
the substring of teHerkennenTemplate isn't taking into account that it starts with a space, which cause the loop to continue forever.
The simplest way to do what you want is with a regular expression:
"test \n test \n".replaceAll("\n", "")
Will return:
"test test "
If you're set on using a loop then this will do the same:
public static String invoerenTemplate(String teHerkennenTemplate)
{
StringBuilder result = new StringBuilder();
while (teHerkennenTemplate.length() > 0)
{
int index = teHerkennenTemplate.indexOf("\n");
result.append(index > -1 ? teHerkennenTemplate.substring(0, index) : teHerkennenTemplate);
teHerkennenTemplate = teHerkennenTemplate.substring(index + 1, teHerkennenTemplate.length());
}
return result.toString();
}

printing a mirrored word using recursion

i need to write a method that takes in a string as a parameter and prints the word in mirrored form. for example, "hello" should return "helloolleh". I have to use recursion and cannot use for loops. Here is my code so far:
public static String printMirrored(String str)
{
if(str == null || str.equals(""))
{
return str;
}
else
{
return str + printMirrored(str.substring(1)) + str.charAt(0);
}
}
My output is "helloellollolooolleh" which obviously has some extra things in there. Any pointers would be greatly appreciated!
Try using str.charAt(0) at the beginning instead of str.
Wrote this real quick. Should do exactly what you want but if you have any questions please let me know.
String word = "hello";
System.out.println(reverseWord(word, word.length()));
public static String reverseWord(String word, int length) {
if(length == 0)
return word;
else
return reverseWord(word + word.charAt(length - 1), length - 1);
}
Recursion is about being the utmost lazy person delegating the rest to a recursive clone.
So on "Hello", take only the "H", get the mirrored result of "ello" and surround it on both ends with an "H".
use StringBuilder.reverse()

Categories