I am trying to get more familiar with recursion in java. I am trying to count number of times character occurs in a given string.
public class apptest {
public static void main(String[] args) {
apptest c = new apptest();
String input = "aaa";
char p = 'a';
c.freq(input, p);
}
public int freq(String c, char p) {
if (c.length() == 0) {
return 0;
} else if (c.charAt(0) == p) {
return 1 + freq(c.substring(1, c.length()), p);
} else
return freq(c.substring(1, c.length()), p);
}
}
I am not getting any output. and completely confused on how to solve a problem like this. I looked online and found the freq(c.substring(1, c.length()),p); part but going through the code it doesn't make sense.. seems like on every pass its still going to deal with 'aa' and not necessarily shrink it.. what am I not seeing?
Your code looks good, but you're not getting output because you're not printing it!
Simply add a System.out.println(...) to your main method.
System.out.println("Frequency is: " + c.freq(input, p));
For this part:
I looked online and found the freq(c.substring(1, c.length()),p); part but going through the code it doesn't make sense.. seems like on every pass its still going to deal with 'aa' and not necessarily shrink it.
The line c.substring(1, c.length()) shrinks the String c so that what gets passed into the recursive call has one less character to process and thus, helping the recursive call to eventually reach the termination condition of c.length() == 0. So, it is safe to assume that freq method's implementation is correct.
Related
I am new to Java, and I'm trying to figure out how to count Characters in the given string and threat a combination of two characters "eu" as a single character, and still count all other characters as one character.
And I want to do that using recursion.
Consider the following example.
Input:
"geugeu"
Desired output:
4 // g + eu + g + eu = 4
Current output:
2
I've been trying a lot and still can't seem to figure out how to implement it correctly.
My code:
public static int recursionCount(String str) {
if (str.length() == 1) {
return 0;
}
else {
String ch = str.substring(0, 2);
if (ch.equals("eu") {
return 1 + recursionCount(str.substring(1));
}
else {
return recursionCount(str.substring(1));
}
}
}
OP wants to count all characters in a string but adjacent characters "ae", "oe", "ue", and "eu" should be considered a single character and counted only once.
Below code does that:
public static int recursionCount(String str) {
int n;
n = str.length();
if(n <= 1) {
return n; // return 1 if one character left or 0 if empty string.
}
else {
String ch = str.substring(0, 2);
if(ch.equals("ae") || ch.equals("oe") || ch.equals("ue") || ch.equals("eu")) {
// consider as one character and skip next character
return 1 + recursionCount(str.substring(2));
}
else {
// don't skip next character
return 1 + recursionCount(str.substring(1));
}
}
}
Recursion explained
In order to address a particular task using Recursion, you need a firm understanding of how recursion works.
And the first thing you need to keep in mind is that every recursive solution should (either explicitly or implicitly) contain two parts: Base case and Recursive case.
Let's have a look at them closely:
Base case - a part that represents a simple edge-case (or a set of edge-cases), i.e. a situation in which recursion should terminate. The outcome for these edge-cases is known in advance. For this task, base case is when the given string is empty, and since there's nothing to count the return value should be 0. That is sufficient for the algorithm to work, outcomes for other inputs should be derived from the recursive case.
Recursive case - is the part of the method where recursive calls are made and where the main logic resides. Every recursive call eventually hits the base case and stars building its return value.
In the recursive case, we need to check whether the given string starts from a particular string like "eu". And for that we don't need to generate a substring (keep in mind that object creation is costful). instead we can use method String.startsWith() which checks if the bytes of the provided prefix string match the bytes at the beginning of this string which is chipper (reminder: starting from Java 9 String is backed by an array of bytes, and each character is represented either with one or two bytes depending on the character encoding) and we also don't bother about the length of the string because if the string is shorter than the prefix startsWith() will return false.
Implementation
That said, here's how an implementation might look:
public static int recursionCount(String str) {
if(str.isEmpty()) {
return 0;
}
return str.startsWith("eu") ?
1 + recursionCount(str.substring(2)) : 1 + recursionCount(str.substring(1));
}
Note: that besides from being able to implement a solution, you also need to evaluate it's Time and Space complexity.
In this case because we are creating a new string with every call time complexity is quadratic O(n^2) (reminder: creation of the new string requires allocating the memory to coping bytes of the original string). And worse case space complexity also would be O(n^2).
There's a way of solving this problem recursively in a linear time O(n) without generating a new string at every call. For that we need to introduce the second argument - current index, and each recursive call should advance this index either by 1 or by 2 (I'm not going to implement this solution and living it for OP/reader as an exercise).
In addition
In addition, here's a concise and simple non-recursive solution using String.replace():
public static int count(String str) {
return str.replace("eu", "_").length();
}
If you would need handle multiple combination of character (which were listed in the first version of the question) you can make use of the regular expressions with String.replaceAll():
public static int count(String str) {
return str.replaceAll("ue|au|oe|eu", "_").length();
}
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);
}`.
I need to find whether a given sub string contains within a given string.But the constraint is I cannot use any predefined Java methods.
I have tried as follows.
public void checkAvailability()
{
len=st.length();
for(int i=0;i<len;i++)
{
for(int j=0;j<substr.length();j++)
{
if(st.charAt(i)==substr.charAt(j))
{
if(j!=substr.length()-1 && i!=st.length()-1)
{
if(st.charAt(i+1)==substr.charAt(j+1))
{
available=true;
//j++;
count++;
}
}
}
}
}
if(available)
{
System.out.println("The character is available " + count + " times");
}
else
{
System.out.println("The character is not availabe");
}
}
But it doesn't give the correct answer. Can somebody help please?
Thank you in advance...
There are a few mistakes in your code - I'll describe an algorithm without writing the code to avoid spoiling the learning exercise for you:
The outer loop needs to go from 0 to st.length()-substr.length()
The inner loop needs to check st.charAt(i+j) and substr.charAt(j)
The inner loop needs to stop as soon as you find a mismatch; set a mismatch flag, and break
If the inner loop completes without finding a mismatch, then i is the position of the first match.
Note that this is the most straightforward algorithm. It does not perform well when the st is long, and substr has lots of "false positives" In general, you can do better than that, for example, by using the KMP algorithm.
Hey I could use a little bit of help to figure out why my program isn't working. The question is to make a program using recursion that figures if it the text given is a palindrome or not after all the punctuation and white spaces are removed. While the program so far compiles, it returns every value as false. We are only allowed to change the isSymmetrical method. I could use whatever help possible trying to figure out how to make this work. Thank you.
public class StringSymmetry {
public static boolean isSymmetrical(String inputText)
{
if(inputText.length() == 0 || inputText.length() ==1)
return true;
if(inputText.charAt(0) == inputText.charAt(inputText.length()-1))
return isSymmetrical(inputText.substring(1,inputText.length()-1));
return false;
}
public static void main(String[] args) {
String[] sampleData =
{ "Don't nod",
"Dogma: I am God",
"Too bad - I hid a boot",
"Rats live on no evil star",
"No trace; not one carton",
"Was it Eliot's toilet I saw?",
"Murder for a jar of red rum",
"May a moody baby doom a yam?",
"Go hang a salami; I'm a lasagna hog!",
"Name is Bond, James Bond"
};
for (String s : sampleData)
{
System.out.println("isSymmetrical (" + s + ") returns " + isSymmetrical(s));
}
}
}
The problem is that you didn't include any checks for case or punctuation and white space.
One way you could do it is something like this. The specifics depend on what you're allowed to use for the assignment, but you're probably intended to do something along these lines.
Also, note that toLowerCase is problematic if you have the default locale set to something unusual like Turkey. For proper robustness, you need to specify a locale, but this isn't something you'll have to worry about in a homework assignment.
public static boolean isSymmetrical(String inputText)
{
inputText = inputText.toLowerCase();
if(inputText.length() == 0 || inputText.length() ==1)
return true;
if(!Character.isLetter(inputText.charAt(0)))
return isSymmetrical(inputText.substring(1,inputText.length()));
if(!Character.isLetter(inputText.charAt(inputText.length()-1)))
return isSymmetrical(inputText.substring(0,inputText.length()-1));
if(inputText.charAt(0) == inputText.charAt(inputText.length()-1))
return isSymmetrical(inputText.substring(1,inputText.length()-1));
return false;
}
Check the following function:
public static boolean isPalindrome(String str, int x) {
if(x == 0) return true;
if(str.charAt(0) == str.charAt((str.length() - 1)))
return isPalindrome(str.substring(1, str.length() - 1), x - 1);
return false;
}
Explanation:
A recursive function with the following parameter's:
str - a String object which will be tested for symmetry.
x - Integer that represent's the recursive tester parameter and decides for how far you want to iterate and check for two sided symmetry.
The base case is set to zero and return's true when you finished the desired iteration number.
The second if-condition statement is used to check the corner's of the string that is given, and its return statement will recursively enter another testing loop with shorter corner's of the original String( . . . corner's will be shorter by one).
Trying to implement contains() method without using built-in method contains().
Here is my code:
public static boolean containsCS(String str, CharSequence cs) {
//char[] chs = str.toCharArray();
boolean result = false;
int i=0;
while(i<str.length()) {
int j=0;
while(j<cs.length()) {
if(NEED TO CHECK IF THERE IS AN INDEX OUT OF BOUNDS EXCEPTION) {
result = false;
break;
}
if(str.charAt(i+j)==cs.charAt(j)) {
result|=true; //result = false or true ->>>>> which is true.
j++;
} else {
result = false;
break;
}
}
i++;
}
return false;
}
Let's say:
String str = "llpll"
Charsequence cs = "llo"
I want to make sure this method works properly in the above case where the Charsequence has one or more char to check but the String runs out length. How should I write the first if statement?
if (i+cs.length() > str.length()){
OUT OF BOUNDS
}
Well if it were me first thing I'd check is that the length of my char sequence was <= to the length of my string.
As soon as you chop that logic path out.
If the lengths are equal you can just use ==
Then it would occur that if you chopped up str
into cs length parts, you could do a straight comparison there as well.
e.g str of TonyJ and search for a three character sequence would pile through
Ton
ony
nyJ
One loop, one if statement and a heck of a lot clearer.
I would suggest using this and using the contains method therein.
Edit - For the reading impaired:
The linked method is not from java.lang.String or java.lang.Object
If you'd bother to actually look at the links, you would see that it is the Apache Commons-Lang API and the StringUtils.contains(...) method that I reference, which very clearly answers the question.
If this is for your homework, which I suspect it is, then I suggest you take a look at the API for the String class to see what other methods are available to help find the location of one String within another.
Also consider looking at the source code for String to see how it implements it.
I'm sure you already know this, but it is in fact possible to see the actual source code of the built-in classes and methods. So I'd take a look there for a start. The String class is especially interesting, IMO.