How to calculate order-complexity of the following algorithm - java

I'm trying to calculate the time complexity of this code that sums the odd numbers of an array. I have done two methods and now I need to calculate the order complexity O(n)
This one is done by weak post-condition.
private static int sumaImparDebilit(int t[], int desde, int hasta) {
if (desde==hasta) {
if ((t[desde] % 2) == 1) {
return t[desde];
}
return 0;
}
if (t[desde]%2 == 1) {
return (t[desde] + sumaImparDebilit(t,(desde+1),hasta));
}
return (sumaImparDebilit(t,(desde+1),hasta));
}
This one is done by strong pre-condition.
private static int sumaImparFortalec(int t[], int hasta, int limite, int parcial) {
if (hasta <= limite) {
if ((t[hasta] % 2) == 1) {
return sumaImparFortalec(t,(hasta + 1),limite,(parcial + t[hasta]));
} else {
return sumaImparFortalec(t,(hasta + 1),limite,(parcial));
}
}
else {
return parcial;
}
}

I don’t know what you mean by “weak” and “strong” conditions, but both have time complexity O(n) and employ (for no good reason) recursion.
Surely this is simplest, and fastest:
int sum = 0;
for (int i = 0; i < t.length; i++)
if (t[i] % 2 == 1)
sum += t[i];

Related

Recursion method that returns number of digits for a given integer

Need to write a method that returns the number of digits foe an integer number.
At first I did it using the iterative approach and everything worked just fine, however, when I want to edit the code using recursion I'm always stuck at the first counting and can't figure out why.
Any help is much appreciated..
public static int numberLength(int n) {
if (n < 0) {
n *= (-1);
} else if (n == 0) {
return 1;
}
int digits = 0;
if (n > 0) {
digits += 1;
numberLength(n / 10);
}
return digits;
In a recursive method you need to return some value based on reducing the size of the input value and combining this with your current count so far e.g.
public static int numberLength(int n){
if(n < 10){
return 1;
}
return 1 + (numberLength(n/10)); //This line combines the result
}
The problem is that you're discarding the result of numberLength(n / 10);
You probably meant to type:
int digits = 0;
if (n > 0) {
return 1 + numberLength(n / 10);
}
return digits;
A possible solution could look like this:
public static int numberLength(int n){
if(n < 0){
return numberLength(-n);
}
else if(n == 0){
return 0;
}
else{
return 1 + numberLength(n/10);
}
}
public static void main(String[] args){
System.out.println(numberLength(-152555)); //returns 6
}

Calculate log base 2 recursion

i'm creating recursion method that calculate Log base 2. for log*(1) = should be 0. log*(4) = should be 2. but my method only print out zero and i couldn't figure out the problem.can some one help me?
public static int logCalculator(double n) {
if (n == 1) {
return 0;
} else {
return 1 + logCalculator(n * n);
}
}
This will work for base 2 logs
public static int logCalculator1(double n) {
if (n < 2)
return 0;
return 1 + logCalculator1(n / 2);
}
NOTE: this will round down always and with high numbers is inaccurate, in addition you can make it for all bases like this:
public static int logCalculator(int base, double n) {
if (base > 0) {
if (n < base) {
return 0;
} else {
return 1 + logCalculator(base, (int)(n / base));
}
} return 0;
}

Java fastest way to get cardinality of BitSet intersection

The function below takes two BitSets, makes a copy of the first (it must not be overridden), intersects the copy with the second (bitwise AND) and returns the cardinality of the result.
public int getIntersectionSize(BitSet bits1, BitSet bits2) {
BitSet copy = (BitSet) bits1.clone();
copy.and(bits2);
return copy.cardinality();
}
I'm interested if this code can be sped up? This function is called billion of times so even a microsecond speed up makes sense plus I'm curious about the fastest possible code.
If you're going to use each BitSet several times, it could be worthwhile to create a long array corresponding to each BitSet. For each BitSet:
long[] longs = bitset.toLongArray();
Then you can use the following method, which avoids the overhead of creating a cloned BitSet. (This assumes that both arrays are the same length).
int getIntersectionSize(long[] bits1, long[] bits2) {
int nBits = 0;
for (int i=0; i<bits1.length; i++)
nBits += Long.bitCount(bits1[i] & bits2[i]);
return nBits;
}
Here is an alternative version, but I'm not sure if it is really faster, depends on nextSetBit.
public int getIntersectionsSize(BitSet bits1, BitSet bits2) {
int count = 0;
int i = bits1.nextSetBit(0);
int j = bits2.nextSetBit(0);
while (i >= 0 && j >= 0) {
if (i < j) {
i = bits1.nextSetBit(i + 1);
} else if (i > j) {
j = bits2.nextSetBit(j + 1);
} else {
count++;
i = bits1.nextSetBit(i + 1);
j = bits2.nextSetBit(j + 1);
}
}
return count;
}
The above is the readable version, hopefully good enough for the compiler, but you could optimize it manually I guess:
public int getIntersectionsSize(BitSet bits1, BitSet bits2) {
int count = 0;
for (int i = bits1.nextSetBit(0), j = bits2.nextSetBit(0); i >= 0 && j >= 0; ) {
while (i < j) {
i = bits1.nextSetBit(i + 1);
if (i < 0)
return count;
}
if (i == j) {
count++;
i = bits1.nextSetBit(i + 1);
}
while (j < i) {
j = bits2.nextSetBit(j + 1);
if (j < 0)
return count;
}
if (i == j) {
count++;
j = bits2.nextSetBit(j + 1);
}
}
return count;
}
I've been looking for a solution to this recently and here's what I came up with:
int intersectionCardinality(final BitSet lhs, final BitSet rhs) {
int lhsNext;
int retVal = 0;
int rhsNext = 0;
while ((lhsNext = lhs.nextSetBit(rhsNext)) != -1 &&
(rhsNext = rhs.nextSetBit(lhsNext)) != -1) {
if (rhsNext == lhsNext) {
retVal++;
rhsNext++;
}
}
return retVal;
}
Perhaps someone would like to take the time to compare the different solutions here and post the results...

why does the loop die? ( Collatz conjecture )

i am trying some math-operations with java, that does test a number if its (un)even and alter it as long as it gets to 1.
I try to run my loop for 999999times, it seems to get stuck at around ~120000times. Well, it is not stopping with an Exception, it just feels like the compiler got stuck.
I'm not that good with Java, can someone explain me what is happening here?
public static void main(String[] args) {
int n = 0;
int highestNumber = 0;
int highestCounter = 0;
int counter = 0;
for (int i = 2;i<1000000;i++) {
if (i%10000==0) {
System.out.println(i);
}
n = i;
while (n!=1) {
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
if (counter>highestCounter) {
highestCounter = counter;
highestNumber = i;
System.out.println("HIGHEST "+highestNumber+" | counter = "+counter);
}
counter = 0;
n = 0;
}
System.out.println("final "+highestNumber);
}
You've got an overflow because 3 * n + 1 became larger than Integer.MAX_VALUE. So n gets negative and the while loop will never halt.
Use long instead of int for n!
If you want to check for the overflow instead:
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
if (n > (Integer.MAX_VALUE - 1) / 3) {
throw new RuntimeException("overflow!");
}
n = 3 * n + 1;
}
counter++;
}
Addition for Java 8
Since Java 8, the Math class provides additional static methods for 'exact' arithmetics (addition, subtraction, multiplication, division) that throw an ArithmeticException in case of an overflow. Using these methods, the code can be simplified:
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
n = Math.addExact(Math.multiplyExact(3, n), 1);
}
counter++;
}
You have an overflow problem. Change the code like this and you see it:
while (n!=1) {
if(n < 0) throw new IllegalStateException("n should not become < 0" + n + "-" + counter);
if(n > ((Integer.MAX_VALUE -1) / 3)) System.out.println("n too large. " + n);
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
if you make n to a long it works fine.
This correction works:
public static void main(String []args){
long highestCounter = -1;
long highestNumber = -1;
for (long i = 2;i<1000000;i++) {
if (i%1000==0) {
System.out.println(i);
}
long n = i;
long counter = 0;
while (n!=1) {
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
if (counter>highestCounter) {
highestCounter = counter;
highestNumber = i;
System.out.println("HIGHEST "+highestNumber+" | counter = "+counter);
}
counter = 0;
n = 0;
}
System.out.println("final "+highestNumber);
}
Hmm, your code looks fine to me. You're solving a pretty typical problem
Is n an integer? If it's a short you might be overflowing it.
Other than that, an integer's max value is over 2 billion, so you shouldn't be hitting it. Just in case, try setting n to a long to see if that helps
Edit: Take for example, the number 77671 According to a blog I read (read: untested) the highest n for i = 77671 is 1,047,216,490
So I think n should be a long, now that I think more about it
You simply running an infinite loop inside while block, add System.out.println(counter); after counter++ to see what's going on..

Write function which is return array of prime factors

I have a function it returns prime factors of a number but when I initialize int array I set size.So the result consists unnecessary zeros.How can I return result array without zeros or how can I initialize array applicable size? I am not using Lists
public static int[] encodeNumber(int n){
int i;
int j = 0;
int[] prime_factors = new int[j];
if(n <= 1) return null;
for(i = 2; i <= n; i++){
if(n % i == 0){
n /= i;
prime_factors[j] = i;
i--;
j++;
}
}
return prime_factors;
}
Thanx!!!
Here is a quick way to get about the prime factors problem that I recently worked out. I don't claim it is original, but I did create it on my own. Actually had to do this in C, where I wanted to malloc only once.
public static int[] getPrimeFactors(final int i) {
return getPrimeFactors1(i, 0, 2);
}
private static int[] getPrimeFactors1(int number, final int numberOfFactorsFound, final int startAt) {
if (number <= 1) { return new int[numberOfFactorsFound]; }
if (isPrime(number)) {
final int[] toReturn = new int[numberOfFactorsFound + 1];
toReturn[numberOfFactorsFound] = number;
return toReturn;
}
final int[] toReturn;
int currentFactor = startAt;
final int currentIndex = numberOfFactorsFound;
int numberOfRepeatations = 0;
// we can loop unbounded by the currentFactor, because
// All non prime numbers can be represented as product of primes!
while (!(isPrime(currentFactor) && number % currentFactor == 0)) {
currentFactor += currentFactor == 2 ? 1 : 2;
}
while (number % currentFactor == 0) {
number /= currentFactor;
numberOfRepeatations++;
}
toReturn = getPrimeFactors1(number, currentIndex + numberOfRepeatations, currentFactor + (currentFactor == 2 ? 1 : 2));
while (numberOfRepeatations > 0) {
toReturn[currentIndex + --numberOfRepeatations] = currentFactor;
}
return toReturn;
}
Allocate as many factors as you think the number may have (32 sounds like a good candidate), and then use Arrays.copyOf() to cut off the array at the actual limit:
return Arrays.copyOf(prime_factors, j);

Categories