Calculating best case run time complexity of recursive algorithm? - java

In class i have started learning how to calculate the run time complexity functions of various algorithms and am finding it difficult. I am trying to calculate the best case rune time complexity of my recursive algorithm below.
At the moment i am choosing my fundamental operation to be a comparison between the index of two chars, and assuming i am trying to find the path where my algorithm outputs a result as soon as possible, i am thinking this first comparison being false would lead my algorithm to do this if i am correct.
Would i be correct in thinking the best case run time complexity function for this algorithm would be t(n) = 1 and in taking the comparison of indexes as a fundamental operation?
public class StringShuffleTest {
public static boolean isOrderedShuffle(String a, String b, String c){
//variables for the size of Strings a, b and c.
int n = a.length();
int m = b.length();
int len = c.length();
//if the length of c is not the length of a + b, return false.
if (len != (n + m)){
return false;
}
//if String c contains String b as a substring, then remove String b from c and make m = 0.
//This statement avoids errors when dealing with Strings with very similar characters.
if (c.contains(b)){
c = c.replace(b, "");
m = 0;
}
//if the length of a or b is 0, and c equals a or b, return true, otherwise,
//return false.
if (n == 0 || m == 0){
if (c.equals(a) || c.equals(b)){
return true;
}
else
return false;
}
//if String a has length 1, remove a from String c and make String a empty.
if (n == 1){
c = c.substring(0, c.indexOf(a.charAt(0))) + c.substring(c.indexOf(a.charAt(0)) +1);
a = "";
return isOrderedShuffle(a, b, c);
}
//An ordered shuffle of two given strings, a and b, is a string that can be formed by interspersing
//the characters of a and b in a way that maintains the left-to-right order of the characters from each
//string.
//Recursive algorithm to determine if String c is an ordered shuffle of a and b.
else
if (c.indexOf(a.charAt(0)) >= 0){
int indexOfFirsta = c.indexOf(a.charAt(0));
int indexOfSeconda = c.indexOf(a.charAt(1));
if (indexOfFirsta <= indexOfSeconda){//Taking as fund operation.
c = c.substring(0, indexOfFirsta) + c.substring(indexOfFirsta +1);
a = a.substring(1, n);
System.out.println(a);
System.out.println(c);
return isOrderedShuffle(a, b, c);
}
else
if (c.indexOf(b.charAt(0)) >= 0){
int indexOfFirstb = c.indexOf(b.charAt(0));
int indexOfSecondb = c.indexOf(b.charAt(1));
if (indexOfFirstb <= indexOfSecondb){
c = c.substring(0, indexOfFirstb) + c.substring(indexOfFirstb +1);
b = b.substring(1, m);
System.out.println(b);
System.out.println(c);
return isOrderedShuffle(a, b, c);
}
}
}
return false;
}
public static void main(String[] args) {
System.out.println(StringShuffleTest.isOrderedShuffle("abc", "def", "abedcf"));
}
}

Related

Finding Greatest Common Divisor using Euclidean Algorithm

I was trying to figure out a solution by which I can find GCD of 2 numbers in most optimal way,
So I need some help here to figure out whether the program I came out works for all possible cases or has any case it will break down or can I improve it more to make it an optimal solution.
Program:
public static void main(String[] args) {
int a= 153;
int b= 81;
boolean flag = true;
int gcd = 1;
while(flag)
{
if(a>b && a%b ==0)
{
flag = false;
gcd = b;
}
else if(b>a && b%a ==0)
{
flag=false;
gcd = a;
}
else if( a>b)
a = a-b;
else
b = b-a;
}
System.out.println(gcd);
}
Kindly help me out in figuring out the proper solution , thanks in advance.
Try something like this. Euclids GCD algorithm basically says this: GCD of 2 numbers (we will call them bigger and smaller) is equal to the GCD of smaller number and difference between bigger and smaller number. Repeat the procedure until two numbers are the same.
The below is iterative solution.
int a= 153 , b = 81, gcd = 1;
while( gcd != a ) {
if( a > b ) a -= b;
else if( b > a) b -= a;
else gcd = a;
}
System.out.println(gcd);
This is recursive solution. Hope this helps.
public static int euclidGCD(int a, int b) {
if (b == a) return a;
if (b > a) return euclidGCD(b - a, a);
else return euclidGCD(a - b, b);
}
Here is a modification of your program.
To test a program the best thing is to write down its conditions and cases.
In this exercise there are two conditions:
1.) Number must be integer
2.) Number must be positive.
Dealing with numbers usually has discrete number of cases. In this exercise there are two cases:
1.) Numbers are equal.
2.) Numbers are different.
Your code is not correct when a is equal to b (try it yourself). When the numbers are different your code works fine. Below is modification.
int a= 55;
int b= 55;
boolean flag = true;
int gcd = b;
while(flag && b != a)
{
if(a>b && a%b ==0)
{
flag = false;
gcd = b;
}
else if(b>a && b%a ==0)
{
flag=false;
gcd = a;
}
else if( a>b)
a = a-b;
else
b = b-a;
}
System.out.println(gcd);

GCD of two polynomials

In the code below I want to find Greatest Common Divisor of 2 polynomials.
Sometimes I am getting error on " return c.plus( (a.minus(b.times(c)).divides(b)) );". How can I fix it?
public Polynomial divides(Polynomial b) {
Polynomial a = this;
if ((b.deg == 0) && (b.coef[0] == 0))
throw new RuntimeException("Divide by zero polynomial");
if (a.deg < b.deg) return new Polynomial(0,0);
int coefficient = a.coef[a.deg]/(b.coef[b.deg]);
int exponent = a.deg - b.deg;
Polynomial c = new Polynomial(coefficient, exponent);
return c.plus( (a.minus(b.times(c)).divides(b)) );
}
public Polynomial GCD(Polynomial b) {
Polynomial a = this;
Polynomial f = b;
Polynomial x = a.minus((a.divides(f)).times(f));
if (x.deg == 0 && x.coef[0] == 0) {
return b;
}
return f.GCD(x);
}
That runtime exception means: you created an endless recursion.
Most likely, because your method divides() is calling itself on that last row - without proper checking in there to avoid that recursion.
In other words: you want to review your maths and the logic in there to simply avoid that divides() keeps calling itself without any limits!

My code does not correctly compare strings of different length

I am supposed to write a compare method that essentially does what the compareTo method does. I have written the code but it does not compare strings of different length.
This is my code:
public static int compare(String a, String b)
{
int result = 0;
a = a.toLowerCase();
b = b.toLowerCase();
//program assumes strings are equal
for (int i = 0; i<a.length() && i<a.length(); i++) {
int c = a.charAt(i);
int d = b.charAt(i);
if (c < d){
result = -1;
break;
}
if (a.length() > b.length()) {
result = -1;
break;
}
if (a.length() < b.length()) {
result = +1;
break;
}
if (c > d) {
result = 1;
break;
}
}
return result;
}
I have done an if loop comparing 2 strings of different lengths but, yet, the program ignores that.
Im trying to understand my mistake so please don't just give me the answer without explaining for I will not learn anything.
Thanks, in advance.
First, you want to make sure, when comparing character by character, that i is less than both a's length and b's length. Right now, you're comparing i to a's length twice.
Try:
// *
for (int i = 0; i<a.length() && i<b.length(); i++){
Second, you only want to compare lengths if you have compared each character equal until one of them has ended. Place the length comparisons after the for loop.
Third, "mars" comes before "marshall", so if a's length is less than b's length, then it compares less also.
// After the for loop ends:
if(a.length() > b.length()){
result = 1;
break; }
if(a.length() < b.length()){
result = -1;
break;

Java: Testing algorithms: all possible combinations

I want to exhaustively test a String matching algorithm, named myAlgo(Char[] a, Char[] b)
The exhaustive test includes a no. of different char letters, alplhabet " l ", in an "n" long array. The test then computes all combinations, while comparing it with all combinations of another array with similar properties (Like truth tables),e.g.
I have not been able to either compute something that would generate every combination of the array of size n and alphabet l, niether have I been able to make code that is able to combine the computation into iterative testcases (test all the combinations of the two arrays compared), though with code that would be able to generate the combinations, making a nested for-loop should do the required testing.
My goal is to break my algorithm by making it compute something it should not compute.
Test(char[] l, int n)
l = [a;b] //a case could be
n = 2 //a case could be
myAlgo([a;a],[a;a]); //loops over my algorithm in the following way
myAlgo([a;b],[a;a]);
myAlgo([b;a],[a;a]);
myAlgo([b;b],[a;a]);
myAlgo([a;a],[a;b]);
myAlgo([a;b],[a;b]);
myAlgo([b;a],[a;b]);
myAlgo([b;b],[a;b]);
myAlgo([a;a],[b;a]);
myAlgo([a;b],[b;a]);
...
myAlgo([b;b],[b;b]);
My own solution (only works for a finite set of "l") and also starts printing wierd outputs on later iterations.
public class Test {
//aux function to format chars
public static String concatChar(char [] c){
String s = "";
for(char cc : c){
s += cc;
}
return s;
}
public static void main(String[] args) {
String ss1 = "AA"; //TestCases, n = 2
String ss2 = "AA";
char[] test1 = ss1.toCharArray();
char[] test2 = ss2.toCharArray();
Fordi fordi = new Fordi(); //my algorithm
TestGenerator tGen = new TestGenerator(); //my testGenerator
for(int i=0; i<Math.pow(4.0, 2.0);i++){ //to test all different cases
for(int j=0; j<Math.pow(4.0, 2.0);j++){
int k = fordi.calculate(test1, test2); //my algorithm
String mys1 = concatChar(test1); //to print result
String mys2 = concatChar(test2); //to print result
System.out.println(mys1 + " - " + mys2);
System.out.println(k);
test2 = tGen.countArray(test2); //"flip" one number
}
test2 = ss1.toCharArray();
test1 = tGen.countArray(test1); //"flip"
}
}
}
My arrayflipper code:
public char[] countArray(char[] a){
int i=0;
while(i<a.length){
switch (a[i]){
case 'A':
a[i]='B';
clearBottom(a,i);
return a;
case 'B':
a[i]='C';
clearBottom(a,i);
return a;
case 'C':
a[i]='D';
clearBottom(a,i);
return a;
case 'D':
i++;
break;
default:
System.out.println("Something went terribly wrong!");
}
}
return a;
}
public char[] clearBottom(char [] a, int i){
while(i >0){
i--;
a[i] = 'A';
}
return a;
}
As I understand it, your goal is to create all n-character long strings (stored individually as elements in an array) consisting of letters in the L letter alphabet?
One way to accomplish this is to order your letters (A=0, B=1, C=2, etc). Then you can, from a starting string of AAA...AAA (n-characters long) just keep adding 1. Essentially you implement an addition algorithm. Adding 1 would turn an A=0 into a B=1. For example, n=3 and L=3:
start: AAA (0,0,0).
Adding 1 becomes AAB (0,0,1)
Adding 1 again become AAC (0, 0, 2)
Adding 1 again (since we are out of letters, now we carry a bit over) ABA (0, 1, 0).
You can boil the process down to looking for the right-most number that is not maxed out and add 1 to it (then all digits to the right of that digit go back to zero). So in the string ABCCC, the B digit is the right-most not maxed out digit, it goes up by 1 and becomes a C, then all the maxed out digits to the right go back to 0 (A) leaving ACAAA as the next string.
Your algorithm just repeatedly adds 1 until all the elements in the string are maxed out.
Instead of using a switch statement, I recommend putting every character you want to test (A, B, C, D) into an array, and then using the XOR operation to calculate the index of each character from the iteration number in a manner similar to the following:
char[] l = new char[]{'A','B','C','D'};
int n = 2;
char[] test1 = new char[n];
char[] test2 = new char[n];
int max = (int)Math.pow(l.length, n);
for (int i = 0; i < max; i++) {
for (int k = 0; k < n; k++) {
test2[k] = l[(i % (int)Math.pow(l.length, k + 1)) / (int)Math.pow(l.length, k)];
}
for (int j = 0; j < max; j++) {
for (int k = 0; k < n; k++) {
test1[k] = l[(j % (int)Math.pow(l.length, k + 1)) / (int)Math.pow(l.length, k)];
}
int k = fordi.calculate(test1, test2);
System.out.println(new String(test1) + "-" + new String(test2));
System.out.println(k);
}
}
You can add more characters to l as well as increase n and it should still work. Of course, this can be further optimized, but you should get the idea. Hope this answer helps!

check whether a string C is an interleaving of A and B

Given three strings A, B and C. Write a function that checks whether C is an interleaving of A and B. C is said to be interleaving A and B, if it contains all characters of A and B and order of all characters in individual strings is preserved.
For example:
'hotdog' is an interleaving of 'hot' and 'dog' (easy)
'superb' is an interleaving of 'up' and 'serb'
'heartache' is an interleaving of 'ear' and 'ache'
'chat' is an interleaving of 'hat' and 'cat'
'cheaters' is not an interleaving of 'chat' and 'seer', because while it contains all the letters from each, the letters from 'seer' do not appear in order
I find some solutions in net but below is my approach can somebody tell me am i missing something or my algo will work? thanks.
My Algo:
Traverse through a and c. While traversal we calculate two things first: whether the char is present or not and save the index i.e. f where the char is found. And as soon as we find the char we should put some special char in that place, so that we will not consider this char further.
For the next char in a search in the c from the index where you have found the previous char i.e. f. if we don't find than return.
Same you do for b as well.
If after doing the above step if we find false than repeat for first b than a and return the result.
e.g.
a = xxy, b = xxz and c = xxzxxxy
start with a:
for x in a, c = 0xzxxxy (i am putting 0 as special char)
for x in a, start from the index 0 onwards(because we have found the previous char at 0)c = 00zxxxy.
for y in a, c = 00zxxx0
for x in b, c = 00z0xx0
for x in b, c = 00z00x0
for z in b, we could not find z after the index 4 which was the index where we found the previous char for b.
as starting with a returns false so we will start with b now.
So start with b:
for x in b, c = 0xzxxxy
for x in b, c = 00zxxxy
for z in b, c = 000xxxy
for x in a, c = 0000xxy
for x in a, c = 00000xy
for y in a, c = 00000x0
hence true i.e.c is the interleaved string of a and b.
Your solution represents a greedy algorithm with a slight modification, because it counts a character in C as belonging to A on the first pass (or to B on the second pass) as soon as it finds a match. This will break for the following strings:
A = xxyxxy
B = xxzxxz
C = xxzxxyxxyxxz
The firs pass that counts a matching character as a member of A will turn C into
00zxx0000xxz
The second pass that counts a matching character as a member of B will turn C into
00000yxxyxx0
Here is a simple Java implementation of a memoized solution:
private static boolean checkOverlap(String a, String b, String c) {
Boolean[][][] memoize = new Boolean[a.length()+1][b.length()+1][c.length()+1];
return checkOverlap(a, b, c, 0, 0, 0, memoize);
}
private static boolean checkOverlap(
String a
, String b
, String c
, int pa
, int pb
, int pc
, Boolean[][][] memoize
) {
Boolean res = memoize[pa][pb][pc];
if (res != null) {
return (boolean)res;
}
if (pa == a.length() && pb == b.length() && pc == c.length()) {
res = true;
} else if (pc == c.length()) {
res = false;
} else {
res = false;
if (pa != a.length() && c.charAt(pc) == a.charAt(pa) && checkOverlap(a, b, c, pa+1, pb, pc+1, memoize)) {
res = true;
} else if (pb != b.length() && c.charAt(pc) == b.charAt(pb) && checkOverlap(a, b, c, pa, pb+1, pc+1, memoize)) {
res = true;
}
}
return (memoize[pa][pb][pc] = res);
}
Demo on ideone.
First, I'd check that the length of A and the length of B summed equal the length of C.
Next, check if the first character of A is equal to the first character of C.
If not, check if the first character of B is equal to the first character of C.
Check the other characters starting with either A or B, depending on which of the two conditions above was true.
Here's a method that will do the test:
public boolean isInterleaved(String a, String b, String c) {
int aIndex = 0;
int bIndex = 0;
int cIndex = 0;
while (cIndex < c.length()) {
if (aIndex < a.length()) {
if (a.charAt(aIndex) != c.charAt(cIndex)) { return false; }
cIndex++;
aIndex++;
}
if (bIndex < b.length()) {
if (b.charAt(bIndex) != c.charAt(cIndex)) { return false; }
cIndex++;
bIndex++;
}
}
return true;
}
You would call this method at most twice. The calls would be either
if (isInterleaved(a, b, c))
or
if (isInterleaved(b, a, c))
If the first character of A and the first character of B are equal, check the other characters starting with the A or B string you didn't start with in the previous step.
This way, you save the complicated testing for the strings that can possibly satisfy the conditions.
def isinterleave(a, b, c):
la = len(a)
lb = len(b)
lc = len(c)
if la + lb != lc: return False
if la == lb == lc == 0: return True
if (la > 0 and lb >0 and a[0] == b[0] == c[0]):
return isinterleave(a[1:], b, c[1:]) or isinterleave(a, b[1:], c[1:])
if (la > 0 and a[0] == c[0]):
return isinterleave(a[1:], b, c[1:])
if (lb > 0 and b[0] == c[0]):
return isinterleave(a, b[1:], c[1:])
return False

Categories

Resources