Recursion string in JAVA - java

I'm writing with JAVA, and I wrote a recursive boolean function that gets 2 strings and is supposed to return if the first one is prefix of the second one.
My code:
public static boolean prefix(String s, String t)
{
int i = s.length()-1;
if (s.charAt(i) == t.charAt(i) && s.length() >= 0)
{
return true;
}
return false;
}
If I'm writing in the main for example:
s = "Del";
f = "Delight";
The function is working as well.
But if I'm writing s = "Dellll", f = "Dell", it says "Out of bounds". Why?
The second thing is that it's not working with big and small characters. For example:
s ="Dell"
f ="dell"
It will return true for the above.
Thank you.

What about using out-of-box solution?
public static boolean prefix(String str, String prefix) {
return str.startsWith(prefix);
}
In case you really need recursion:
public static boolean prefix(String str, String prefix) {
if (str == null || str.isEmpty())
return prefix == null || prefix.isEmpty();
if (prefix == null || prefix.isEmpty())
return true;
if (str.charAt(0) != prefix.charAt(0))
return false;
// remove first character of each string and go to next iteration
return prefix(str.substring(1), prefix.substring(1));
}

This is because you declare i as:
int i = s.length()-1;
And then call the ith char in both Strings
if (s.charAt(i) == t.charAt(i) && s.length() >= 0)
But if the first String is bigger than the second then i will be out of bounds. An easier way to do this would be to use the built in method startsWith, which:
Tests if this string starts with the specified prefix.
So your method could be as simple as:
return t.startsWith(s);
Or if you can't use built in methods, then you'll need to check if the first String is larger that the second:
if (s.charAt(i) == t.charAt(i) && s.length() >= 0 && s.length() < t.length())

Out of bounds means that, being the second string shorter than the first one, you are trying to access a character that doesn't exist. Just check the two lengths at the beginning of the function, and switch the parameters internally if needed.

Related

Recursive implementation of indexOf

I've already read many previous questions here and elsewhere, but I haven't found what I need.
I need to write a recursive implementation of indexOf. The problem is that I can't use any local variables and have to give as input only a string and a char.
The method should return a value between 0 and the length of the string - 1 if the char has been found or -1 if it is not there.
I know the actual 'indexOf' allows you to search for a string too, but this method is simplified.
I tried this but it's quite stupid since I used the real indexOf:
public static int indexOf(String s, char c){
if(s.indexOf(c) < 0){ // I'd like to change this
return -1;
}
if (s.length() == 0) //base case #1
{
return -1;
}
else if (s.charAt(0) == c) //base case #2
{
return 0;
}
else {
return 1 + indexOf(s.substring(1), c);
}
}
I saw this in particular, but is it possibile to write it without variables? Thanks
If you don't want local variables, you need to do the recursion in an internal method.
Advantage is that it's a lot faster, since it doesn't have to create new String objects, and the logic is tail-recursive, if used with a language that optimizes that.
public static int indexOf(String s, char c) {
return indexOf0(s, c, 0);
}
private static int indexOf0(String s, char c, int index) {
if (index == s.length())
return -1;
if (s.charAt(index) == c)
return index;
return indexOf0(s, c, index + 1);
}
The answer that you linked seems to be a good one... I recommend simply replacing the instances of the variable used in it with the method call the variable stores.
Below I simply edit the code:
public static int indexOf(char ch, String str) {
// Returns the index of the of the character ch
if (str == null || str.equals("")) {
// base case: no more string to search; return -1
return -1;
} else if (ch == str.charAt(0)) {
// base case: ch is at the beginning of str; return 0
return 0;
}
return indexOf(ch, str.substring(1)) == -1 ? -1 : 1 + indexOf(ch, str.substring(1));
}

How to let my code also check strings with length 0?

I am trying to remove the letter x if it is present as the first or last character of any given string. Why does my code not check strings with length 0 even though I have accounted for it in my code?
I have already tried using an if statement to check if the length is 0 and, if so, to return the original string. I have also tried returning an empty string with the same value.
public String withoutX(String str) {
if (((str.charAt(0)=='x') || str.charAt(str.length()-1) == 'x') && str.length()>=2){
if (str.charAt(0)=='x'){
str = str.substring(1,str.length());
} if (str.charAt(str.length()-1) == 'x'){
str = str.substring(0,str.length()-1);
}
} if (str.length()==1 && str == "x"){
return "";
} if (str.length()==0){
return str;
// the above if statement (length = 0) does not work
} else{
return str;
}
}
The expected result is for it to return the string without the letter x. This has been achieved for all strings, except an empty one, where it says that the index is out of range.
if (str.length() == 0) {
return str;
}
It should be at the top of the method body. Or, at least, it should go prior to getting str.charAt(0).
There's String#isEmpty.
The way you compared Strings is wrong. Use equals instead of ==.
Always validate the length before accessing a letter by index. Make sure that index in a string exists.
In this line:
if (((str.charAt(0)=='x') || str.charAt(str.length()-1) == 'x') && str.length()>=2)
you do check for the length of the string but after you check the indexes.
Change to:
if (str.length()>=2 && (str.charAt(0)=='x' || str.charAt(str.length()-1) == 'x'))
if str.length()>=2 is false the other conditions will not be checked because of Short Circuit Evaluation.
Also use equals() to compare strings and not ==.
I vwould write your method like this:
public String withoutX(String str) {
if (str.length() == 0 || (str.length() == 1 && str.equals("x")))
return "";
if (str.charAt(0) == 'x') {
str = str.substring(1, str.length());
}
if (str.charAt(str.length() - 1) == 'x') {
str = str.substring(0, str.length() - 1);
}
return str;
}
I kept your logic and removed unnecessary code.
I think this is a better implementation of what you are trying to do
public String withoutX(String str) {
if (str.startsWith("x")){
str = str.replaceFirst("x", "");
}
if (str.endsWith("x")){
str = str.substring(0,str.lastIndexOf("x"));
}
return str;
}
A simpler approach without making many corner-cases checking is to use regex to remove the leading and trail x - if it exists. Here's the code:
public String withoutX(String str){
return "".equals(str)? str: str.replaceAll("(^x|x$)", "");
}
Your code is checking for a x before you check if the string is empty. You should move
if (str.length()==0){
return str;
// the above if statement (length = 0) does not work
}
to the first line of the method. Besides that your code is great.
public String withoutX(String str) {
if (!str.isEmpty() && str.charAt(0)=='x'){
str = str.substring(1, str.length());
}
if (!str.isEmpty() && str.charAt(str.length()-1) == 'x'){
str = str.substring(0,str.length()-1);
}
return str;
}
You can first check, if the str is empty and remove the first x. Then check the size for greater than 1 and remove the last x. This leads to less and more readable code.

Search() StringIndexOutOfBoundsException

I was asked in a problem to make a static recursive method called search that searches for a character in a string and if it finds it prints it's location, if it doesn't, it returns -1
this is my code
public static int search(String s , char c)
{
boolean flag = true;
if (flag == false && s.length() == 0)
return -(s.length() + 1);
else
if (s.charAt(0) == c)
{
return 1;
}
else
{
flag = false;
return 1 + search(s.substring(1) , c);
}
I'm using a flag to see if it doesn't find it after coursing through all the string, it'll preform all of the string's length minus the string's length - 1,
But I always end up with a "StringIndexOutOfBoundsException" error. Where is that error located exactly? Thanks in advance! :D
edit: it works if i input a character that exists in the string like n in animal, but if i enter o and the string be animal , it'll give me the error.
edit 2: I got it to work by removing the flag and traversing the string from the last character, thanks everyone! :D
I guess the first index out of bounds will happen at else block s.substring(1)...
ex: s="a", c="b"
flag=true
if (flag == false && s.length() == 0) this will fail and go to else block
in else block, if (s.charAt(0) == c) , here "a"=="c" fails go to else block
in the inner else block, you have return 1 + search(s.substring(1) , c); this line will look for the String index
position 1, which is not available and throws
stringindexoutofboundsexception
Because of your recursion flag is always true so your first if will never be true.
It would help if flag would be a class member. In that case you need to reset the flag before each search.
But it would also leads to an exception if you invoke your search with an empty string. So I think you do not need the flag.
If you dint mind searching from the end of the string you can do this:
public static int search(String s , char c) {
if (s==null || s.length() == 0)
return -1;
else if (s.charAt(s.length()-1) == c)
{
return s.length();
} else {
int pos=search(s.substring(0,s.length()-1) , c);
return pos;
}
}
There are few small issues with your code.
flag is always true, so if conditions is always false:
boolean flag = true;
if (flag == false && s.length() == 0) // always false, even if
// s.length() is 0
Why do you need this flag variable? This assignment flag = false; has no effect by the way. You either need to change signature of your search method search(String s , char c, boolean flag) and pass it as 3rd param, or probably remove flag completely.
Second thing is that your function will return positive result for all strings will lengths more than 2 characters.
return 1 + search(s.substring(1) , c); and return -(s.length() + 1);. The last condition will be executed only if there are no more characters in the string (let's say we are not using flag variable).
if (s.length() == 0) // there are no more characters in the str
return -(s.length() + 1); // we return -1
But in this case we already have return 1 + search(s.substring(1) , c); which will lead to 1 + -(0+1). for search("a",'d'),
1 + 1 -(0+1) for search("ab",'d') and so on.
I hope this helps.
Error comes from return 1 + search(s.substring(1) , c); this line.
if you are searching for 'o', in the last iteration s=l and s.substring(1) doesn't exist
You have to move out the flag variable outside the method, as on every recursive call it is being set to true and hence the first if block will never get executed. loopCount will meet your purpose, you don't need to use flag variable.
static int loopCount =0;
public static void main( String[] args )
{
System.out.println(search("animal", 'o'));
}
public static int search(String s , char c)
{
loopCount++;
if (s.length() == 0){
return -loopCount;
}
else if (s.charAt(0) == c)
{
return 1;
}
else
{
return 1 + search(s.substring(1) , c);
}
}

How can I count the number of some specific characters in a string recursively?

I was practicing recursion problem. there are some type of questions wants you to count the number of specific characters in a String without loop.
What kind of method should I use? can anyone explain to me?
Here is the question:"Given a string, compute recursively (no loops) the number of lowercase 'x' chars in the string."
my code:
public int countX(String str) {
if(str.length()==0){
return 0;
}
if(str.charAt(0)=='x'){
return 1+ countX(str.substring(1));
}
return countX(str);
}
You're almost there, but you need to revise the case where the first letter in str isn't 'x'. What you are currently doing will cause infinite recursion because in the case where str.charAt(0) != 'x', you recursively call countX on str. However, str is still the same string that didn't have 'x' as its first letter, so it's going to call countX on str again and again and again, etc.. So the solution is to only call countX on str.substring(1) when its first letter isn't 'x' like so,
public int countX(String str) {
if(str.length()==0){
return 0;
}
if(str.charAt(0)=='x'){
return 1 + countX(str.substring(1));
}
else{
return countX(str.substring(1));
}
}
What your method was doing before
Let's say I called countX on "Hello", here's how the call stack trace would look like,
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello")
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello")
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("Hello");
.
.
.
infinite recursion
What the new solution does
call countX("Hello")
"Hello".length() != 0 so we move on to the next condition
"Hello".charAt(0) != 'x' so we call countX("ello")
call countX("ello")
"ello".length() != 0 so we move on to the next condition
"ello".charAt(0) != 'x' so we call countX("llo")
call countX("llo")
"llo".length() != 0 so we move on to the next condition
"llo".charAt(0) != 'x' so we call countX("lo");
call countX("lo")
"lo".length() != 0 so we move on to the next condition
"lo".charAt(0) != 'x' so we call countX("o");
call countX("o")
"o".length() != 0 so we move on to the next condition
"o".charAt(0) != 'x' so we call countX("");
call countX("")
"".length() == 0 so return 0
return 0
return 0
return 0
return 0
return 0
Notice how in the solution, we always have a way of getting to the base case (str.length()==0). Whereas before, there would be instances (when we encountered a letter that wasn't x) that would prevent the method from reaching the base case.
What kind of method should I use? can anyone explain to me?
one solution is to use a StringBuilder and simply delete the first character at each invocation of the method, eventually, you'll get to the base case and should output the correct result.
public int countX(String str) {
if(str.length() == 0) return 0;
StringBuilder builder = new StringBuilder(str);
if(str.charAt(0) == 'x'){
builder.deleteCharAt(0);
return 1 + counter(builder.toString());
}
builder.deleteCharAt(0);
return counter(builder.toString());
}
However, if you wish to proceed with your current solution, you'll need to replace this:
return countX(str);
with this:
return countX(str.substring(1));
the problem was that if the current character is not 'x' you simply ignored it and didn't simplify the problem towards the base case.
I understand your need. In below, you have the method you need to count recursively a character in a string.
static int countCharRecursively(String str, char ch){
if(str.indexOf(ch) != -1)
{
return countCharRecursively(str.substring(0, str.indexOf(ch)), ch)+
countCharRecursively(str.substring(str.indexOf(ch)+1),ch) + 1;
}
else{
return 0;
}
}
Here is a complete program you can run.
public class CountCharRecursivelyInString{
public static void main(String[] args){
String str = "hello the world";
char ch = 'l';
int nbr = countCharRecursively(str, ch);
System.out.println(ch + " : " + nbr);
}
static int countCharRecursively(String str, char ch){
if(str.indexOf(ch) != -1)
{
return countCharRecursively(str.substring(0, str.indexOf(ch)), ch)+
countCharRecursively(str.substring(str.indexOf(ch)+1),ch) + 1;
}
else{
return 0;
}
}
}

Java if-statement being skipped

The method below takes in a string and a pattern and returns true if they match each other. A '.' matches 1 char and a '*' matches 0 or more (e.g. expMatch("abc", "a.c") should return true). I added a bunch of print statements to see where I went wrong and it seems like the if statement is being skipped even if the str.length() == 1.
I call it with System.out.println(expMatch("abc", "a*c"));
Here is the code:
public static boolean expMatch(String str, String pat)
{
if (str.charAt(0) == pat.charAt(0) || pat.charAt(0) == '.')
{
System.out.println("in if");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
System.out.println(str.length());
if (str.length() == 1)
return true;
expMatch(str.substring(1), pat.substring(1));
}
else if (pat.charAt(0) == '*')
{
System.out.println("in else");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
if (str.length() == 1)
return true;
if (str.charAt(0) == pat.charAt(1)) //val of * = 0
expMatch(str, pat.substring(1));
else if (str.charAt(1) ==pat.charAt(1))
expMatch(str.substring(1), pat.substring(1));
}
return false;
}
and the output is:
in if
a
a
3
in else
b
*
in if
c
c
1
false
Even if the length is 1 it skips the if? Any idea why?
P.S. I'm not looking for the solution, just why the if statement is being skipped.
You always return false from the method at the very end. You are calling expmatch recursively but never using the return value. The code comes in to the first if, recurses (because length is not 1) and upon returning will go to the final return statement which returns false.
You need to add a return before your expMatch() calls - because the false comes from your last line return false;
What happens is this:
you call expMatch() with the two Strings.
you enter the if clause
the if clause enters expMatch() recursively
you enter the else clause
the else clause enters expMatch() recursively
you enter the if clause again
you leave the expMatch() method
you leave the other expMatch method
false is returned
Your approach is logically incorrect even if you apply the fixes the others suggested. Try this test case:
System.out.println(expMatch("abddddc", "a*c"));
This is because when you encounter a * in the pattern, you have no way to know how many characters "to eat" from the search string.
To say the least, you need a loop somewhere, not just an if. Let me try to fix it for you (not sure if it's possible though, not sure if you always know which path to take, I mean in your recursion). Think some more about it. Here is another unpleasant test case:
System.out.println(expMatch("adddcac", "a*c"));
// the * needs to eat dddca (despite the c present in dddca),
// it should not stop recursing there at that c
I think you need some sort of full search here.
Just an if or a while loop is not good enough.
EDIT: Here is a fixed version with a bunch of nasty tests. I think this is called non-linear recursion (as it's not a single path you try). Not 100% sure though about that term.
public class Test055 {
public static void main(String[] args) {
// System.out.println(expMatch("abddddc", "a*c"));
System.out.println(expMatch("adcax", "a*c"));
System.out.println(expMatch("adcax", "a*c*"));
System.out.println(expMatch("adcacm", "*"));
System.out.println(expMatch("adcacmmm", "a*c"));
System.out.println(expMatch("adcacmmmc", "a*c"));
System.out.println(expMatch("adcac", "a*c"));
System.out.println(expMatch("adcacxb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c*b"));
}
public static boolean expMatch(String str, String pat)
{
// System.out.println("=====================");
// System.out.println("str=" + str);
// System.out.println("pat=" + pat);
if (pat.length() == 0 && str.length() > 0) {
return false;
} else if (pat.length() == 0 && str.length() == 0) {
return true;
} else if (pat.charAt(0) == '.'){
return str.length() >= 1 && expMatch(str.substring(1), pat.substring(1));
}else if (pat.charAt(0) != '*'){
return str.length() >= 1 && pat.charAt(0) == str.charAt(0) && expMatch(str.substring(1), pat.substring(1));
}else{
// Now let's handle the tricky part
// (1) Look for the 1st non-star in pattern
int k=-1;
char ch = ' ';
for (int i=0; i<pat.length(); i++){
if (pat.charAt(i) != '*'){
k = i;
ch = pat.charAt(k);
break;
}
}
if (k==-1){
// (2A) only stars found in pattern, OK, any str matches that
return true;
}else{
// (2B) do full search now checking all
// possible candidate chars in str that
// match the char ch from pattern
for (int i=0; i<str.length(); i++){
if (str.charAt(i)==ch){
boolean b = expMatch(str.substring(i+1), pat.substring(k+1));
if (b) return true;
}
}
return false;
}
}
}
}

Categories

Resources