Finding number of sub strings between two giving chars - java

I need for my homework to write method that get two parameters, string and char, and it needs to return the number of strings that start with that char and end with that char.
Example:
For the string "abcbcabcacab" and the char 'c', the method will return 6.
(the sub strings are "cbc", "cabc", "cac", "cbcabc", "cabcac", "cbcabcac")
It needs to be as effectiveness as possible, and the only two method that I can use is charAt() and length().This is hard as hell and after 3 hours of trying, I'm asking you guys if there is someone who cal solve this or at least show me some clue.

The obvious solution is to check every symbol in input string and if equals to specified char, then try to find all possible substrings, starting from this point, like this:
long cnt = 0;
for (int i = 0; i < (s.length() - 1); i++)
if (s.charAt(i) == c)
for (int j = (i + 1); j < s.length(); j++)
if (s.charAt(j) == c)
cnt++;
return cnt;
this solution has complexity O(N^2)
but, number of substrings actually determined by number of occurrences of char in string, which appeared to be Triangular number
So, optimized O(N) solution is:
long cnt = -1;
for (int i = 0; i < s.length(); i++)
if (s.charAt(i) == c)
cnt++;
return (cnt * (cnt + 1)) >>> 1;

The simplest anwser is that you should use a loop.
Loop through the strings. Check if the current string starts with the given char and ends with the given char. If it doesn't just jump to the next one. if it does just loop with a counter from 1 to length minus the second last char.
You will reduce time by kicking out invalid string and you will be checking 2 chars less EVERY string ;)
I guess that's a quite fast way.
Example
// String definition bla String[] myArray
int count = 0;
for(int i = 0; i < myArray.length(); i++) {
if(myArray[i].charAt(0) == givenChar && myArray[i].charAt(myArray.length()-1)) {
for(int j = 1; j < myArray.length()-2;j++) {
if(myArray[i].charAt(j) == givenChar)
count ++;
}
}
}
That's the rough idea.
I am checking if the given String starts and ends with the givenChar.
If it does im iterating through the string checking for the givenChar again.
If it does exist i am counting 1 up.
I hope that might help your out ;)
Have a nice day!

Related

How to Optimise a given problem time complexity?

I have a question which says
Given an input
ababacad
The output should be all the a's should come first together rest characters should follow their sequence as they were originally. i.e.
aaaabbcd
I solved it like below code
String temp="", first="" ;
for(int i=0;i<str.length;i++) {
if(str.charAt(i)!='a')
temp=temp+str.charAt(i);
else
first=first+str.charAt(i);
}
System.out.print(first+temp);
The output matches but it says it is still not optimised. I guess its already order of N complexity. Can it be optimised further.
Optimization here can mean string operations as well as the number of iterations. So, just to be on the safe side, you can implement it using arrays. The time complexity will be O(n) which is the minimum for this problem as you have to check every position for the presence of char 'a'.
String input = "ababacad";
char[] array = input.toCharArray();
char[] modified = new char[array.length];
int a = 0; // index for a
int b = array.length - 1; // index for not a
for (int i = array.length - 1; i >= 0; --i) {
if (array[i] != 'a')
modified[b--] = array[i];
else
modified[a++] = array[i];
}
String output = new String(modified);
System.out.println(output);

Finding all Strings of Length

Given a class Password of all the passwords that can be written with only the lowercase letters of the English alphabet, I'd like to write an algorithm which recursively finds a password, by going over all of the possible passwords of the same length.
The class Password has a method public boolean isPassword(String st), which compares between a given password p and the string st and returns the boolean value of whether or not they're equal.
Let's call this method public static String findPassword(Password p, int length).
My idea was to do this in two recursive calls - one that goes on the length of p, and continuously adds characters from the alphabet with the method charAt(i) on the string alphabet="abcd.....z" until it gets a string at the same length as p (meaning length).
The second recursive call will go on the letters of the alphabet creating new strings by changing each time the letter that it adds to the previous string. For instance, given a string st of length L, we'll first add the letter a, then the letter b, and so on until we get to z, to move from strings of length L to length L+1.
My problem at the moment is translating some of these ideas into code, and I'd like to do this without any for loops.
If you did it as simple for loops you'd do this:
// For n=1
for (int i = 0; i < 26; i++)
System.out.println(alphabet.substring(i, i + 1));
// For n=2
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
System.out.println(alphabet.substring(i, i + 1) +
alphabet.substring(j, j + 1));
// For n=3
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
for (int k = 0; k < 26; k++)
System.out.println(alphabet.substring(i, i + 1) +
alphabet.substring(j, j + 1) +
alphabet.substring(k, k + 1));
And so on. That would generate the following for n=3:
aaa
aab
aac
...
aaz
aba
...
zzz
Now, since you can't hardcode number of nested loops for dynamic values of n, you use recursion, as you said, but only one recursive call as you progress from 1 to n.
This means the recursive method need to receive two parameters: The string so far, and the number of letter left to add.
When in the deepest recursive call, i.e. when no more letters needs to be added, print the result.
Here is pseudo-code:
method(String textSoFar, int lettersLeft) {
if (lettersLeft == 0)
print textSoFar
else
for each letter in alphabet:
method(textSoFar + letter, lettersLeft - 1)
}
You initiate the recursion by calling method("", n).
Remember, you can't return the strings, because you'll build lots of strings for increasing values of n:
26 strings for n=1
676 strings for n=2
17,576 strings for n=3
456,976 strings for n=4
11,881,376 strings for n=5
and progressively worse...

Java cannot find symbol for loops, logic problems?

Ok, my program in this specific section takes a line of data from a studentAnswer string array, the value of which would be something like TTFFTFTFTF. I am supposed to take this, and compare it against a key array, which might look like TFFFTFTFTF. A student takes a quiz, and my program calculates the points correct.
My intention is to use a separate points array to find the numeric grade for the student. The index of studentAnswer refers to a specific student. So studentAnswer[i] is TTFFTFTFTF. I use substrings to compare each individual T/F against the correct answer in key[], which would have a single T/F in each index. Then, if they are correct in their answer, I add a 1 to the correlating index in points[] and will later find the sum of points[] to find the numeric grade out of ten.
My problem here is that String origAns, used to define the student's original answer string, is getting a Java Error cannot find Symbol. I have tried placing the instantiation of origAns within each different for loop, but I can't get the program to work. Int i is meant to follow each specific student- I have four parallel arrays that will all log the student's ID number, numeric grade, letter grade, and original answers. So that is the intention of i, to go through each student. Then j should be used to go through each of these original student answer strings and compare it to the correct answer...
Logically, it makes sense to me where I would put it, but java doesn't agree. Please help me to understand this error!
for (int i = 0; i < studentAnswer.length; i++){
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++){
if (origAns.substring[j] == key[j]){
//substring of index checked against same index of key
points[j] = 1;
}
if (origAns.substring[j] != key[j]){
points[j] = 0;
}
}
}
It sounds like you're trying to call the substring method - but you're trying to access it as if it were a field. So first change would be:
if (origAns.substring(j) == key[j])
Except that will be comparing string references instead of contents, so you might want:
if (origAns.substring(j).equals(key[j]))
Actually, I suspect you want charAt to get a single character - substring will return you a string with everything after the specified index:
if (origAns.charAt(j) == key[j])
... where key would be a char[] here.
You can also avoid doing the "opposite" comparison by using an else clause instead.
You should also indent your code more carefully, for readability. For example:
for (int i = 0; i < studentAnswer.length; i++) {
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++) {
if (origAns.charAt(j) == key[j]) {
points[j] = 1;
} else {
points[j] = 0;
}
}
}
And now, you can change that to use a conditional expression instead of an if/else:
for (int i = 0; i < studentAnswer.length; i++) {
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++) {
points[j] = origAns.charAt(j) == key[j] ? 1 : 0;
}
}
When you call a method in Java, you use parentheses () instead of brackets [].
Since substring is a method, you should call it like so
if (origAns.substring(j) == key[j])
A few other notes, you should use the equals method for comparisons (especially those comparisons involving Strings.)
if (origAns.substring(j).equals(key[j]))
Also, you should use charAt to extract a single character at some position in a string. substring(j) will return a string of characters starting at position j.
if (origAns.charAt(j).equals(key[j]))
Your explanation is very long and I have not read it from the beginning to end. But I can see at least one problem in your code:
if (origAns.substring[j] == key[j])
You are comparing strings using == instead of using method equals():
if (origAns.substring[j].equals(key[j]))
Substring is a function, not a member, of String objects. Check out the example at the top of this page:
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html
Notice the use of parenthesis instead of brackets.
If you are using a String use charAt function
String studentAnswer = "TTFFTFTFTF";
for (int i = 0; i < studentAnswer.length(); i++)
{
char origAns = studentAnswer.charAt(i);
}
Else if you are using an char array then
char studentAnswer[] = "TTFFTFTFTF".toCharArray();
for (int i = 0; i < studentAnswer.length; i++){
char origAns = studentAnswer[i];
}

String index out of range: n

Im having a bit of a problem with this code each time i execute it it gives me an error
String index out of range: 'n'
n - is the no. of characters that is entered in the textbox pertaining to this code...
(that is textbox - t2.)it is stuck at that first textbox checking it does not go over to the next as mentioned in the array.
Object c1[] = { t2.getText(), t3.getText(), t4.getText() };
String b;
String f;
int counter = 0;
int d;
for(int i =0;i<=2;i++)
{
b = c1[i].toString();
for(int j=0;j<=b.length();j++)
{
d = (int)b.charAt(j);
if((d<65 || d>90)||(d<97 || d>122))
{
counter++;
}
}
}
it is basically a validation code that i am trying to do without exceptions and stuff(still in the process of learning :) )
any help would be appreciated
thx very much.
Use <, not <= when iterating over the string. With <=, you get an out of bounds error, when j equals the length of the string. Remember that characters in the string are indexed starting from zero.
for(int j = 0; j < b.length(); j++)
In java string.charAt(string.length()) will be out of bounds since the string is 0 indexed and so the last character is at string.length() - 1.
Strings are indexed starting at 0. Your second for loop is set to end at b.length, which will always be 1 greater than the highest index for that string., Change it to j < b.length instead.

More efficient way to find all combinations?

Say you have a List of Strings or whatever, and you want to produce another List which will contain every possible combination of two strings from the original list (concated together), is there any more efficient way to do this other than using a nested for loop to combine the String with all the others?
Some sample code:
for(String s: bytes) {
for(String a: bytes) {
if(!(bytes.indexOf(a) == bytes.indexOf(s))) {
if(s.concat(a).length() == targetLength) {
String combination = s.concat(a);
validSolutions.add(combination);
}
}
}
}
The time for execution gets pretty bad pretty quickly as the size of the original list of Strings grows.
Any more efficient way to do this?
You can avoid checking i != j condition by setting j = i + 1. Also, things like bytes.length() get evaluated at each iteration of both loops - save it into a value and reuse. Calling a.length() inside the loop asks for a length of the same string multiple times - you can save some runtime on that as well. Here are the updates:
int len = bytes.length();
int aLength;
String a, b;
for(int i=0; i<len; i++) {
a = bytes[i];
aLength = a.length();
for(int j=i; j<len; j++) {
b = bytes[j];
if (b.length() + aLength == targetLength) {
validSolutions.add(b.concat(a));
validSolutions.add(a.concat(b));
}
}
}
Edit: j = i because you want to consider a combination of a string with itself; Also, you'd need to add a.concat(b) as well since this combination is never considered in the loop, but is a valid string
You can't get Better than O(N^2), because there are that many combinations. But you could speed up your algorithm a bit (from O(N^3)) by removing the indexOf calls:
for(int i=0; i<bytes.length(); i++) {
for(int j=0; j<bytes.length(); j++) {
string s = bytes[i];
string a = bytes[j];
if (i != j && s.length() + a.length() == targetLength) {
validSolutions.add(s.concat(a));
}
}
}
In addition to what Jimmy and lynxoid say, the fact that the total length is constrained gives you a further optimization. Sort your strings in order of length, then for each s you know that you require only the as such that a.length() == targetLength - s.length().
So as soon as you hit a string longer than that you can break out of the inner loop (since all the rest will be longer), and you can start at the "right" place for example with a lower-bound binary search into the array.
Complexity is still O(n^2), since in the worst case all the strings are the same length, equal to half of totalLength. Typically though it should go somewhat better than considering all pairs of strings.

Categories

Resources