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));
}
Related
This question already has answers here:
Check string for palindrome
(42 answers)
Closed 2 years ago.
Problem is to check if the string is valid palindrome or not. Return true for empty strings.
What's the problem with my code? It is failing for the input "ab"
public class Solution {
Boolean b;
public Boolean isPalindrome(String s) {
s = s.toLowerCase();
s = s.replaceAll("[^a-zA-Z0-9]","");
if(s.length()==1 || s.isEmpty())
{
return true;
}
for (int i=0;i<s.length()-1;i++)
{
b = expandAroundCenter(s,i,i+1);
b = expandAroundCenter(s,i,i);
}
return b;
}
public Boolean expandAroundCenter(String s,int start,int end)
{
while(start>=0 && end<s.length() )
{
if ((s.charAt(start))!=(s.charAt(end)))
{
return false;
}
start--;
end++;
}
return true;
}
}
You've got big logic flaws here.
Firstly, in your for loop you call expandAroundCenter twice, and overwrite the first results.
Secondly, you're doing this in a for loop, and overwriting all previous results.
Also I think you're making things harder than they need to be by starting in the middle. Start on the edges, and work inward!
Calculating a palindrome is a great opportunity for a recursive function (one that calls itself). I'll give you the pseudo-code, it's up to you to implement:
public Boolean IsPalindrome(string s)
// If we are down to 1 or zero characters, success!
// This deals nicely with odd numbered length strings
if(length <= 1)
return true;
// If the first and last don't match, it's not a palindrome
if(first letter != last letter)
return false;
// Since we know the first and last match, strip them off, then repeat
return IsPalindrome(strip first and last letter from string)
}
If there are no constraints, the best way to solve this problem is to use recursive.
class palindrome
{
static boolean isPalRec(String str,
int s, int e)
{
if(s == "")
return true;
if (s == e)
return true;
if ((str.charAt(s)) != (str.charAt(e)))
return false;
if (s < e + 1)
return isPalRec(str, s + 1, e - 1);
return true;
}
static boolean isPalindrome(String str)
{
int n = str.length();
if (n == 0)
return true;
return isPalRec(str, 0, n - 1);
}
}
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.
Why doesn't my palindrome program work correctly? It always returns false, and I can't tell why.
Here is my code:
public static boolean isPalindromIterative(String string) {
int a = 0;
int b = string.length() - 1;
while (b > a) {
if (a != b) {
return false;
}
a++;
b--;
}
return true;
}
You are comparing values of a and b which aren't the same when you start comparing and hence you get false from your method.
In your if condition, Change it to be string.charAt(a) != string.chatAt(b)
When you say
while (b > a) {
if (a != b) {
It's clear that a is not equal to b (or the loop wouldn't be entered). Going by context, I believe you wanted to compare the characters in the String. I would use String.toCharArray() to get a char[] and do something like
char[] chars = string.toCharArray();
while (b > a) {
if (chars[a] != chars[b]) {
If b > a in your code while (b > a), then a doesn't equal to b in your code if (a != b).
To check given string is palindrome or not in java simply use StringBuilder class reverse() method and check with given string.
public static boolean isPalindromIterativeStringBuilder(String string) {
StringBuilder sb = new StringBuilder(string);
sb.reverse(); //Reverse to the given string
return sb.toString().equalsIgnoreCase(string); //Check whether given string is equal to reverse string or not
}
This is also an iterative method.
I would be happy if I helped someone. ;)
public static boolean isPalindromeIterative(String string) {
String polindromCheck = string.toUpperCase();
for (int index = 0; index < polindromCheck.length(); index++) {
if (polindromCheck.charAt(index) != polindromCheck.charAt(string.length() - 1 - index)) {
return false;
}
}
return true;
}
EDIT: Really sorry, I mean Java! As for what I think, I would say the first contains if statement is for s == null or length 0, but I'm confused as to what to put in the
return spaceCount(s.substring(1, ......)) + ......;
part.
I'm trying to use some if statements to write a function that takes a string as a parameter and recursively coutns the number of blanks spaces " " it has. So far I have
public static int spaceCount (string s) {
if ( ...... ) {
return 0;
}
char c = s.charAt(0);
if (....... ) {
return spaceCount (.....);
} else {
return spaceCount(s.substring(1, ......)) + ......;
}
}
So in the first if statement, should I write the case of the string having zero length? I'm pretty sure that won't cover the case of no spaces at all, so I'm not sure how to proceed.
For the second and third, I know I have to scan the string for spaces, but I am not really sure how to do that either. Any hints or direction would be appreciated!
public static int spaceCount(final String s) {
if(s == null || s.length() == 0) {
return 0;
}
char c = s.charAt(0);
if(' ' != c) {
return spaceCount(s.substring(1));
} else {
return spaceCount(s.substring(1)) + 1;
}
}
You don't have to "scan the string for spaces", that's what the recursion passing the remainder of the string does.
s.length() - s.replaceAll(" ", "").length() returns you number of spaces.
how to count the spaces in a java string? has the answer. Probably it may help. the above line is the simplest.
[You didn't specify a programming language] Here is a solution in Java:
public static int spaceCount(String s)
{ return scRecursive (s, s.length, 0, 0); }
public static int scRecursive (String s, int len, int dex, int count)
{ if (len == dex) return count;
else
return scRecursive (s, len, dex + 1,
(' ' == s.charAt(dex) ? count + 1 : count)); }
This is tail recursive (which might imply some efficiency) and, more importantly, this does not copy/allocate substrings
Here is one in Scheme:
(define (space-count string)
(let ((length (string-length string)))
(let stepping ((index 0) (count 0)
(if (= index length)
count
(let ((char (string-ref string index)))
(stepping (+ index 1)
(if (equal? #\space char)
(+ 1 count)
count)))))))
The recursion is in the call to stepping which has two arguments - the current index and the current count of spaces. The recursion terminates when the index equals the length. The count is incremented when the current char is a space.
public class CountSpaces {
public static void main(String[] args) {
String str = " A ";
System.out.println(spaceCount(str, 0));
System.out.println(spaceCount(str));
}
public static int spaceCount(String str, int count) {
if (str == null) {
return 0;
} else if (str.length() > 0) {
char c = str.charAt(0);
if (Character.isWhitespace(c)) {
count++;
}
return spaceCount(str.substring(1), count);
} else {
return count;
}
}
public static int spaceCount(String s) {
if (s.length() == 0 || s == null) {
return 0;
}
char c = s.charAt(0);
if (!Character.isWhitespace(c)) {
return spaceCount(s.substring(1));
} else {
return spaceCount(s.substring(1, s.length())) + 1;
}
}
}
Here is what I have for method lastIndexOf , ch is the character to match, and str is the source string.
public static int lastIndexOf(char ch, String str) {
// check for null string or empty string
if (str.length() == 0 || str == null) {
return -1;
}
int indexInRest = lastIndexOf(ch, str.substring(1));
char first = str.charAt(0);
// recursive call to find the last matching character
if (first == ch) {
return 1 + indexInRest; // this might not work properly
} else
return indexInRest;
}
If in my class' main method I call:
System.out.println(lastIndexOf('r', "recurse"));
System.out.println(lastIndexOf('p', "recurse"));
I got:
1
-1
The desired result is:
4
-1
Suggestion, please.
How about taking the functional approach..
public static int lastIndexOf(char ch, String str) {
if (str.charAt(str.length() - 1) == ch) { return str.length() -1; }
if (str.length() <= 1) { return -1; }
return lastIndexOf(ch, str.substring(0, str.length() - 1));
}
This must be homework because there would be no point to writing this method since String.lastIndexOf() exists in the API, and using recursion to do this going to be slow and use a lot of memory.
Here a hint. Right now your algorithm is chopping characters off the front ( substring(1) ) and comparing them. lastIndexOf() should start by removing characters at the back of the String looking for a match then quit when it finds one.
why not use String.lastIndexOf like this:
str.lastIndexOf(ch)
Use the String#lastIndexOf(int ch) implementation as a general guideline,
public int lastIndexOf(int ch) {
return lastIndexOf(ch, value.length - 1);
}
public int lastIndexOf(int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
int i = Math.min(fromIndex, value.length - 1);
for (; i >= 0; i--) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return lastIndexOfSupplementary(ch, fromIndex);
}
}
private int lastIndexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
final char[] value = this.value;
char hi = Character.highSurrogate(ch);
char lo = Character.lowSurrogate(ch);
int i = Math.min(fromIndex, value.length - 2);
for (; i >= 0; i--) {
if (value[i] == hi && value[i + 1] == lo) {
return i;
}
}
}
return -1;
}
And this,
lastIndexOf(ch, value.length - 1);
value is the target String as a character array.
First, you should change to:
if (str == null || str.length() == 0) {
Because a NPE could raise if str is null
Add a deep paramater to your code like this:
public static int lastIndexOf(char ch, String str, int deep) {
And increment its value every recursive call
int indexInRest = lastIndexOf(ch, str.substring(1), deep++);
then, in the return sentence, add deep to your returned value:
return 1 + indexInRest + deep; // this might not work properly
Call the function the first time with deep = 0, or better yet, make the two parameter method lastIndexOf call the 3 parameters version of lastIndexOf with the deep parameter set to 0
You can also use Matcher in order to anticipate evolution of string analysis asked by your homework:
public int getlastMatch(String searchPattern,String textString) {
int index = -1;
Pattern pattern = Pattern.compile(searchPattern);
Matcher matcher = pattern.matcher(textString);
while(matcher.find()) {
index = matcher.start();
}
return index;
}
where textString may be your concerned character.
Thus returning the last occurence of a part of string within a string.