I am trying to write a method that uses recursion to compare the strings str1 and str2 and determine which of them comes first alphabetically (i.e., according to the ordering used for words in a dictionary).
If str1 comes first alphabetically, the method should return int 1.
If str2 comes first alphabetically, the method should return the int 2.
If the two strings are the same, the method should return the int 0.
I know that there is a compareTo method in the Java API but i would like to know how to do this without this
This is what i have so far but i'm not entirely sure how to proceeded
} if (str1.length().equals(str2.length()))
return 0;
} else {
(str.substring(1, str.length()));
Any ideas would be greatly appreciated
Make a method int recursiveCompare(String string1, String string2, int index). Initially call it with index = 0. Compare string1.charAt(index) and string2.charAt(index), and if they're different, return 1 or 2. If they're the same, return recursiveCompare(string1, string2, index + 1).
Of course, you'll have to check the lengths of string1 and string2 before calling charAt(index). If they both reach the end at the same time, they're equal, so return 0. Otherwise, return the number of the one that has ended.
And yeah, recursion is pretty much the worst way to do this, LOL.
No recursion required... (Unless this is specifically required in the homework(?) assignement...)
As this looks a lot like homework, I'll just give a few hints
Use a integer variable, say i, to index from 0 to the length of shorter string.
As long as str1[i] == str2[i], and the last index value hasn't been reached, increment i.
If you do reach the last possible value for the index, then the shorter string comes first (or they are deemed equal if same length...)
Otherwise, compare this first character that differs, and decide which string is first accordingly... Could be as simple as:
return (str1[i] < str2[i]);
If recursion you must... (and it was readily said in other comments, this kind of problem is truly not a logical/valid candidate for recursion...)
The idea is to have a function with this kind of interface:
int RecursCompare(string str1, string str2, int i)
and which calls itself, passing the same values for str1 an str2 and passing the next value for i (i+1), as long as str1[i] == str2[i] AND neither str1 or str2 is at its end.
When this condidtion becomes false, recursion ends, and instead the function returns the appropriate value to signify tha Str1 is alphabetically before or after Str2.
#include<stdio.h>main(){ char str1[100],str2[100]; int i=0,k=0; puts("Enter string 1"); gets(str1); puts("Enter string 2"); gets(str2); i=comp(str1,str2,0); printf("\ncount is %d %d \n",i,strlen(str1)); (strlen(str1)==strlen(str2)) ?( (strlen(str1)==i) ? printf("Both are equal"):printf("Both are Not equal")):printf("Both are Not equal"); }int comp(char s1[], char s2[],int i){ printf("\n%c %c",s1[i],s2[i]); int sum=0,count =1; if((s1[i] != '\0')|| (s2[i]!='\0')) { if (s1[i] == s2[i]) { return (count += comp(s1,s2,++i)); } else { return 0; } } else { return 0; } return count; }
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();
}
This function should take two strings str1 and str2 and use recursion to determine and return the number of differences between the two strings – i.e., the number of positions at which the two strings have different characters. If one string is longer than the other, all of its extra characters should count as differences.
public static int numDiff(String str1, String str2){
// recursive case
int numOccurInRest = numDiff(str1.substring(1), str2.substring(1));
if (str1.charAt(0) == str2.charAt(0)) {
return 1 + numOccurInRest;
} else {
return numOccurInRest;
}
}
It's giving me an error that it is out of the index. but I am more sure how to make it recursively.
I have a problem in understanding how the following code is executed. I am seeking an example for 1/2 executions.
Code is:
public class StringArray {
public static String getFirstString(String[] values) {
if (values.length == 0) {
return "";
}
String result = values[0];
for (int i=1; i<values.length; i++) {
if (result.compareTo(values[i]) > 0) {// i.e. result > values[i]
result = values[i];
}
}
return result;
}
public static void main(String[] args) {
String[] nume= {"Andrei", "Andreea", "Andrea",
"Marius", "Marcus", "Marcel", "Florin"};
System.out.println(getFirstString(nume));
}
}
Basically, is the first item processed?
First is Andrei.
1.Andrei will get into the first If? values.length should not be 7?
1.1 "value" being the reference of the parameter, should point to the array[] name which is given in the main method, right?
Therefore, Andrei will be compared to Andreea, but from here, why is Andrei bigger than Andreea? I have a hard time with the if (result.compareTo(values[i]) > 0).
The key element here: understanding the "contract" of the compareTo() method.
Start by looking at the javadoc:
Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. The character sequence represented by this String object is compared lexicographically to the character sequence represented by the argument string. The result is a negative integer if this String object lexicographically precedes the argument string. The result is a positive integer if this String object lexicographically follows the argument string. The result is zero if the strings are equal; compareTo returns 0 exactly when the equals(Object) method would return true.
This is the definition of lexicographic ordering. If two strings are different, then either they have different characters at some index that is a valid index for both strings, or their lengths are different, or both. If they have different characters at one or more index positions, let k be the smallest such index; then the string whose character at position k has the smaller value, as determined by using the < operator, lexicographically precedes the other string. In this case, compareTo returns the difference of the two character values at position k in the two string -- that is, the value:
this.charAt(k)-anotherString.charAt(k)
If there is no index position at which they differ, then the shorter string lexicographically precedes the longer string. In this case, compareTo returns the difference of the lengths of the strings -- that is, the value:
this.length()-anotherString.length()
I was working on a Java coding problem and encountered the following issue.
Problem:
Given a string, does "xyz" appear in the middle of the string? To define middle, we'll say that the number of chars to the left and right of the "xyz" must differ by at most one
xyzMiddle("AAxyzBB") → true
xyzMiddle("AxyzBBB") → false
My Code:
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)result=false;
if(str.length()==3 && str.equals("xyz"))result=true;
for(int j=0;j<str.length()-3;j++){
if(str.substring(j,j+3).equals("xyz")){
String rightSide=str.substring(j+3,str.length());
int rightLength=rightSide.length();
String leftSide=str.substring(0,j);
int leftLength=leftSide.length();
int diff=Math.abs(rightLength-leftLength);
if(diff>=0 && diff<=1)result=true;
else result=false;
}
}
return result;
}
Output I am getting:
Running for most of the test cases but failing for certain edge cases involving more than once occurence of "xyz" in the string
Example:
xyzMiddle("xyzxyzAxyzBxyzxyz")
My present method is taking the "xyz" starting at the index 0. I understood the problem. I want a solution where the condition is using only string manipulation functions.
NOTE: I need to solve this using string manipulations like substrings. I am not considering using list, stringbuffer/builder etc. Would appreciate answers which can build up on my code.
There is no need to loop at all, because you only want to check if xyz is in the middle.
The string is of the form
prefix + "xyz" + suffix
The content of the prefix and suffix is irrelevant; the only thing that matters is they differ in length by at most 1.
Depending on the length of the string (and assuming it is at least 3):
Prefix and suffix must have the same length if the (string's length - the length of xyz) is even. In this case:
int prefixLen = (str.length()-3)/2;
result = str.substring(prefixLen, prefixLen+3).equals("xyz");
Otherwise, prefix and suffix differ in length by 1. In this case:
int minPrefixLen = (str.length()-3)/2;
int maxPrefixLen = minPrefixLen+1;
result = str.substring(minPrefixLen, minPrefixLen+3).equals("xyz") || str.substring(maxPrefixLen, maxPrefixLen+3).equals("xyz");
In fact, you don't even need the substring here. You can do it with str.regionMatches instead, and avoid creating the substrings, e.g. for the first case:
result = str.regionMatches(prefixLen, "xyz", 0, 3);
Super easy solution:
Use Apache StringUtils to split the string.
Specifically, splitByWholeSeparatorPreserveAllTokens.
Think about the problem.
Specifically, if the token is in the middle of the string then there must be an even number of tokens returned by the split call (see step 1 above).
Zero counts as an even number here.
If the number of tokens is even, add the lengths of the first group (first half of the tokens) and compare it to the lengths of the second group.
Pay attention to details,
an empty token indicates an occurrence of the token itself.
You can count this as zero length, count as the length of the token, or count it as literally any number as long as you always count it as the same number.
if (lengthFirstHalf == lengthSecondHalf) token is in middle.
Managing your code, I left unchanged the cases str.lengt<3 and str.lengt==3.
Taking inspiration from #Andy's answer, I considered the pattern
prefix+'xyz'+suffix
and, while looking for matches I controlled also if they respect the rule IsMiddle, as you defined it. If a match that respect the rule is found, the loop breaks and return a success, else the loop continue.
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)
result=false;
else if(str.length()==3 && str.equals("xyz"))
result=true;
else{
int preLen=-1;
int sufLen=-2;
int k=0;
while(k<str.lenght){
if(str.indexOf('xyz',k)!=-1){
count++;
k=str.indexOf('xyz',k);
//check if match is in the middle
preLen=str.substring(0,k).lenght;
sufLen=str.substring(k+3,str.lenght-1).lenght;
if(preLen==sufLen || preLen==sufLen-1 || preLen==sufLen+1){
result=true;
k=str.length; //breaks the while loop
}
else
result=false;
}
else
k++;
}
}
return result;
}
I am trying to overwrite the compareTo in Java such that it works as follows. There will be two string arrays containing k strings each. The compareTo method will go through the words in order, comparing the kth element of each array. The arrays will then be sorted thusly. The code I have currently is as follows, but it does not work properly.
I need a return statement outside the for-loop. I'm not sure what this return statement should return, since one of the for-loop return statements will always be reached.
Also, am I using continue correctly here?
public int compareTo(WordNgram wg) {
for (int k = 0; k < (this.myWords).length; k++) {
String temp1 = (this.myWords)[k];
String temp2 = (wg.myWords)[k];
int last = temp1.compareTo(temp2);
if (last == 0) {
continue;
} else {
return last;
}
}
}
You want to compare the two string at the same location:
int last = temp1.compare(temp2);
Java compiler mandates all the end points must have a return statement. In your case you must return 0 at end so when both arrays contain completely equal strings the caller will know they are equal.
You should start listening to your compiler, because after looking at your code for 1 minute, I spotted two undefined states: this.myWords.length is 0 and the two words are equal.
Also, I personally find it very difficult to handle multiple method exit points with all possibilities for input considered and rather insert a single returning statement which makes debugging easier and the results more predictable. In your case for example, I would collect the results of compareTo in a collection if they differ from 0 so that after the for-loop has finished, you could decide at the state of this collection if 0 (empty collection) or the first value in the collection could be returned. I like this more formal approach, because it enforces you to think set-like as in "Give me all comparing results where compareTo results in anything else but 0. If this list is empty, the comparing result is 0, otherwise it is the first element of the list."