Reputation: 123
I'm practicing pretty basic recursion problems in Java.
"Given a string, compute recursively (no loops) the number of lowercase 'x' chars in the string"
countX("xxhixx") → 4
countX("xhixhix") → 3
countX("hi") → 0
-
public int countX(String str) {
if (str == null || str.length() == 0)
return 0;
else if (str.length() == 1)
return str.charAt(0) == 'x' ? 1 :0;
else {
return (str.charAt(str.length()-1) == 'x' ? 1 : 0 ) + countX(str.substring(0,str.length()-1));
}
}
This works fine. But, I would like to know if there is any better way of writing it. I find this code complex for a simple problem.
Upvotes: 4
Views: 1509
Reputation: 114230
The main reason you think this is cumbersome is that it is. A recursive solution is just generally not optimal for counting things in a string or array. Besides the fact that the code looks strange, at least to me, you are actually creating a new stack frame and a new version of the string for every character. This is inefficient (although I wonder if String.substring
is optimized to point to the original buffer instead of making a full copy, given that strings are immutable).
However, given the constraints of your problem, you could probably get rid of a few redundant checks that you do in your code:
public int countX(String str) {
if(str == null || str.isEmpty())
return 0;
return (str.charAt(0) == 'x' ? 1 : 0) + countX(str.substring(1));
Since you already test for null
and empty strings, a string of length 1 is no longer a special case.
By removing the first character at each iteration instead of the last, you make the indexing and the call to substring
much cleaner. This also removes two explicit calls to str.length()
.
Upvotes: 6
Reputation: 4020
Try this:
public int countX(String str) {
if (str == null)
return 0;
else {
int occurrence = str.lastIndexOf("x");
int count = occurrence > -1 ? 1 + countX(str.substring(0, occurrence)) : 0;
return count;
}
}
Upvotes: 1
Reputation:
The else if (str.length() == 1)
is not necessary as this condition is already been handled by the return (str.charAt(...
I don't think it can be improved more than that. Actually, I think the problem is too simple to use recursion (using a loop would be pretty much simpler, but as you can't use it...) and the code would be more complicated than needed anyway.
Upvotes: 0
Reputation: 121998
This looks more clear ?
public static int countX(String str) {
if (str.length() == 0) {
return 0;
}
int count = 0;
if (str.charAt(0) == 'x') {
count++;
}
return count + countX(str.substring(1));
}
Upvotes: 1
Reputation: 311143
The special treatment for a string of length 1 is redundant - it's already covered by the else
clause:
public int countX(String str) {
if (str == null || str.length() == 0)
return 0;
}
return (str.charAt(str.length()-1) == 'x' ? 1 : 0 ) +
countX(str.substring(0,str.length()-1));
}
Upvotes: 1