everyone. I am very new to java so I hope my question does not sound dumb, but I am encountering trouble with an online exercise.
Basically, I need to write a recursive method, in java, called reverse that accepts a String parameter and returns a string concatenated with its reverse. So, for example, if the string was "Java" it returns it as "JavaavaJ"
I worked out most of the code, but cannot figure out how to combine the two in the return method.
public static String reverse(String str) {
if ((null == str) || (str.length() <= 1)) {
return str;
}
return reverse(str.substring(1)) + str.charAt(0);
}
You'll want to prepend the string you're reversing with the first character as well. Something like this should work:
public String reverse(String str) {
if (null == str) {
return null;
}
if (str.length() <= 1) {
return str + str;
}
return str.charAt(0) + reverse(str.substring(1)) + str.charAt(0);
}
Without prepending the first character, the recursion would just produce a reverse of the string. Similarly, appending the whole string twice when you are at the last character is needed as well (e.g., "a" reversed using this logic seems like it should produce "aa")
Related
Question
Given a string, if the string "del" appears starting at index 1, return a string where that "del" has been deleted. Otherwise, return the string unchanged.
My Code
public String delDel(String str) {
return str.replaceAll("del","");
}
but my code failed for some test cases like:
1)delDel("del") → "del" ""
2)delDel("aadelbb") → "aadelbb" "aabb"
I am beginner to Java. Can anyone tell me why it's showing that error.
Question link : https://codingbat.com/prob/p100905
Thanks in advance...
Here String::replaceFirst should be used with a simpler regexp "^(.)del" because only the first occurrence at the beginning of the string needs to be matched:
public String delDel(String str) {
return str.replaceFirst("^(.)del", "$1");
}
Another solution may use String::regionMatches (or even shorter String::startsWith) and String::charAt + String::substring to perform the task without regular expressions at all:
public String delDel(String str) {
return str.startsWith("del", 1) ? str.charAt(0) + str.substring(4) : str;
// return str.regionMatches(1, "del", 0, 3) ? str.charAt(0) + str.substring(4) : str;
}
For this Kata, i am given random function names in the PEP8 format and i am to convert them to camelCase.
(input)get_speed == (output)getSpeed ....
(input)set_distance == (output)setDistance
I have a understanding on one way of doing this written in pseudo-code:
loop through the word,
if the letter is an underscore
then delete the underscore
then get the next letter and change to a uppercase
endIf
endLoop
return the resultant word
But im unsure the best way of doing this, would it be more efficient to create a char array and loop through the element and then when it comes to finding an underscore delete that element and get the next index and change to uppercase.
Or would it be better to use recursion:
function camelCase takes a string
if the length of the string is 0,
then return the string
endIf
if the character is a underscore
then change to nothing,
then find next character and change to uppercase
return the string taking away the character
endIf
finally return the function taking the first character away
Any thoughts please, looking for a good efficient way of handing this problem. Thanks :)
I would go with this:
divide given String by underscore to array
from second word until end take first letter and convert it to uppercase
join to one word
This will work in O(n) (go through all names 3 time). For first case, use this function:
str.split("_");
for uppercase use this:
String newName = substring(0, 1).toUpperCase() + stre.substring(1);
But make sure you check size of the string first...
Edited - added implementation
It would look like this:
public String camelCase(String str) {
if (str == null ||str.trim().length() == 0) return str;
String[] split = str.split("_");
String newStr = split[0];
for (int i = 1; i < split.length; i++) {
newStr += split[i].substring(0, 1).toUpperCase() + split[i].substring(1);
}
return newStr;
}
for inputs:
"test"
"test_me"
"test_me_twice"
it returns:
"test"
"testMe"
"testMeTwice"
It would be simpler to iterate over the string instead of recursing.
String pep8 = "do_it_again";
StringBuilder camelCase = new StringBuilder();
for(int i = 0, l = pep8.length(); i < l; ++i) {
if(pep8.charAt(i) == '_' && (i + 1) < l) {
camelCase.append(Character.toUpperCase(pep8.charAt(++i)));
} else {
camelCase.append(pep8.charAt(i));
}
}
System.out.println(camelCase.toString()); // prints doItAgain
The question you pose is whether to use an iterative or a recursive approach. For this case I'd go for the recursive approach because it's straightforward, easy to understand doesn't require much resources (only one array, no new stackframe etc), though that doesn't really matter for this example.
Recursion is good for divide-and-conquer problems, but I don't see that fitting the case well, although it's possible.
An iterative implementation of the algorithm you described could look like the following:
StringBuilder buf = new StringBuilder(input);
for(int i = 0; i < buf.length(); i++){
if(buf.charAt(i) == '_'){
buf.deleteCharAt(i);
if(i != buf.length()){ //check fo EOL
buf.setCharAt(i, Character.toUpperCase(buf.charAt(i)));
}
}
}
return buf.toString();
The check for the EOL is not part of the given algorithm and could be ommitted, if the input string never ends with '_'
public String reverse(String word) {
if ((word == null) || (word.length() <= 1)) {
return word;
}
return reverse(word.substring(1)) + word.charAt(0);
}
I have this code that professor sent me but I don't get it. I know what recursion is but I'm still a newbie at Java Programming so if anybody would care to explain to me the part
return reverse(word.substring(1)) + word.charAt(0);
what does the subString(1) does and the chartAt(0)?
This is recursion. Here are documentation for subString() and charAt().
Coming to how this works:
public static String reverse(String word) {
if ((word == null) || (word.length() <= 1)) {
return word;
}
return reverse(word.substring(1)) + word.charAt(0);
}
Pass1: reverse("user") : return reverse("ser")+'u';
Pass2: reverse("ser")+'u' : return reverse("er")+'s'+'u';
Pass3: reverse("er")+'s'+'u' : return reverse("r")+'e'+'s'+'u';
Pass4: reverse("r")+'e'+'s'+'u' : return 'r'+'e'+'s'+'u'; // because here "r".length()==1
The way the recursive part of this works is that to reverse a string, you remove the first character, reverse what's left, and then append the first character to the result. That's what the prof's code is doing.
word.substring(1) returns the substring starting at index 1 and going to the end
word.charAt(0) returns the character at index 0
There's a bit more going on when the two pieces are appended using +. The issue is that word.charAt(0) has a return type of char. Since the left-hand part of the + is a String, the Java language rules say that the right-hand side must be converted to a String if it isn't one. So the char value is first converted to a Character and then the toString() method of the Character class is called. This returns a String consisting of the single character.
It might have been more efficient code to write that line like:
return reverse(word.substring(1)) + word.substring(0, 1);
The two-argument version of substring returns the substring between the two indexes. That would eliminate the autoboxing and conversion to String.
return reverse(word.substring(1)) + word.charAt(0);
you should read it this way:
remove the first letter away from the word
reverse the rest (recursive call)
put the first letter at the end
if you assume this function reverses the strings of length N, you can easily see that it must reverse the strings of length N+1. If you realize that the word with at most one letter is the same if reversed (the first three lines of code), you have a complete very simple proof using Mathematical Induction that this function really reverses the string.
I have two simple examples to support my question. I can't figure out why (1) is working while (2) isn't. In my opinion I use them the same way.
(1)
public String frontBack(String str) {
if (str.length() <= 1) return str;
String mid = str.substring(1, str.length()-1);
// last + mid + first
return str.charAt(str.length()-1) + mid + str.charAt(0);
}
(2)
public String front22(String str) {
str = "test";
return str.charAt(0);
}
With the second one, I get an type mismatch error that says: Cannot convert from char to string. When I try to find an answer on internet I see the str declared as a var type in all examples. But it works with the first example.
What am I missing?
In the first example you return a String. In the second you (try to) return a char.
Since you do string concatenation in the first example the result of the expression is a string.
To return the first character as a String:
return str.substring(0,1);
You can fix it by typing
return "" + str.charAt(0);
Somehow that forces the character into a string.
So I'm having a little trouble with the final part of my assignment on recursion. The method needs to use recursion to return a string that is formed from "weaving" together two strings taken in as parameters. For example:
weave("aaaa", "bbbb") // should return the string "abababab"
weave("hello", "world") // should return the string "hweolrllod"
weave("recurse", "NOW") // should return the string "rNeOcWurse"
Note that the extra characters from the first string—the characters in "urse"—come after the characters that have been woven together.
The important (and annoying) thing is that I'm not allowed to use any iteration loops (for, while, do while).
Here is my code thus far:
public static String weave(String str1, String str2)
{
String word = str1 + str2;
if(str1 == null || str1.equals("") || str2 == null || str2.equals(""))
{
return word;
}
String word1 = weave(str1.substring(0, str1.length() - 1), str2.substring(0, str2.length() - 1));
System.out.println(word1);
return word;
}
For (Hello, World), my output is:
HW
HeWo
HelWor
HellWorl
HelloWorld
Obviously my characters aren't weaving, so I'm not sure what to do! Also, as stated above, the method should do not printing. I just added in the println statement as a test to see where my program was at.
I think something like the following might work.
public String weave(String str1, String str2)
{
if(str1.isEmpty() || str2.isEmpty()) {
return str1 + str2;
}
return str1.substring(0, 1) + str2.substring(0, 1) + weave(str1.substring(1), str2.substring(1));
}
The idea is pretty simple: you only need to pop the first character from both input strings and concatenate both characters and the returned value from calling the function recursively with the stripped input strings until one of the input strings is empty in such case you should merely return the non-empty string.
weave("abcdef", "12"): "a" + "1" + weave("bcdef", "2")
|
+- weave("bcdef", "2"): "b" + "2" + weave("cdef", "")
|
+- weave("cdef", ""): "cdef"
Resulting in:
weave("abcdef", "12"): "a" + "1" + "b" + "2" + "cdef": "a1b2cdef"
The problem with your code is:
String word = str1 + str2;
//...
return word;
No matter how the recursive call, at the end it just return the result from the first method call when you pass in "hello", "world".
String word = str1 + str2; //hello + world
//... other things and the recursive call doesn't matter
//return word; //return the first word variable which is helloworld