Simple Algorithm complexity - java

I have an algorithm and I need help finding the complexity of it (tightest possible upper bound)
for(int i = 0; i < n/2; i++)
for(int j = 0; j < n/4; j++)
for(int k = 0; k < n; k++)
x++;
My analysis is that if n would not be divided in each for loop, it would be O(n^3). This complexity still holds true, since each "for loop" will reduce each operation to a O(log n) complexity since it divides n every time the loop executes, making it smaller and smaller (smaller than O(n) at least).
I would say that the answer is between O(log n) and O(n^3). Could you help me getting the tightest possible bound?

start with inner loop :
for(int k = 0; k < n; k++)
x++;
is obviously O(n).
now one layer above that :
for(int j = 0; j < n/4; j++)
is O(n) because it takes n/4 for j to reach the n and we know that O(n/4) = O(n)
and like this for outer loop is O(n).so the complexity is O(n^3) because you have three nested loop each with O(n) and non of them have effect on each other.

Assume each step takes time C.
For k-loop, time taken is Cn.
For j-loop, time taken to complete iteration is (Cn)n/4=C(n^2)/4
For i-loop, time taken to complete iteration is (C*(n^2)/4)n/2=C(n^3)/8
So Total time taken=(C/8)*(n^3)
As C/8 is a constant it can be ignored when considering Big-O Notation.
Thus, Time Complexity=O(n^3).

for(int i = 0; i < n/2; i++) --> n/2
for(int j = 0; j < n/4; j++) --> n/4
for(int k = 0; k < n; k++) --> n
x++;
Hence total complexity is O((n^3)/8) which is O(n^3)

Related

Complexity Analysis that makes every element in the array equal to largest element

What is the complexity of the given code as a function of the problem size n? Show the details
of your analysis.
for (int i = 0; i < 2*n; i++)
{
if (i == n)
{
for (int j = 0; j < i; j++)
for (int k = 0; k < i; k++)
O(1)
}
else
{
for (int j = 0; j < i; j++)
O(1)
}
}
My thoughts so far:
The if statements could not always be true (could be log n)
Nested inner for loops are n^2.
Any help on how to solve it or how to proceed with it would be appreciated.
Thank you.
Without the if(i == n) {} , the number of operation is :
1 + 2 + 3 + 4 + 5 + ... + n*2
= (2n * (2n-1))/2
But at i==n , the number of operations is not i like the rest, it's i².
So the final number of operations is :
((2n * (2n-1))/2) - n + n²
The Big O notation of the above is O(n²)

Big O for multi loops

count++;
count++;
count++;
for (int i = 0; i < n; i++)
{
for(int j = 0; j < i*i; j++)
{
for (int k = 0; k < j; k++)
{
count++;
sum++;
}
}
}
count++;
return count;
}
Trying to get the Big O of this coding. Struggling to understand how the loops interact. When I run it, I get n = 25 count = 898960. I've tried O(n)^5+9 all the way to O(n)^5/n
All other examples of this problem don't deal with I is used in the second loop (I*I) and j is used in the third loop
Almost always the best way to compute complexities of kinda loops should be done by making use of sigma notation.
P.S. I don't write necessary +1s in the formulas since it is not important for Big-O notation and doesn't affect max power which is 5.
It looks like it is O(n^5).
for (int i = 0; i < n; i++) // 0 to n -> O(n)
for(int j = 0; j < i*i; j++) // 0 to n * n -> O(n^2) repeated n times -> O(n^3)
for (int k = 0; k < j; k++) // 0 to n * n -> O (n^2) repeated O(n^3) times -> O(n^5)
In the best case scenario, three nested loops would give you O(n^3), but as you have the second loop repeat (n^2) times, that will square its complexity and of the third loop as well. So in a simple mathematical notation that will be: (n) * (n * n) * (n * n) = n^5.

Nested for loops but with a twist

So recently I am having trouble understanding nested for loops. For example, one question asks: The following nested loop structure will execute the inner most statement (x++) how many times?
for (int j = 0; j < 100; j++)
{
for (int k = 100; k > 0; k--)
{
x++;
}
}
Can you keep it in simple terms, as I am fairly new to programming? Thanks!
For every inner loop, the for loop will execute x++ 100 times. You will also run the inner for loop 100 times. So in total you will run x++ 100 x 100 = 10000 times.
For each j, the k loop executes a 100 times hence incrementing x by 100. See illustration below:
for j=0; k=100, k=99, k=98 .... k=2, k=1; x is now 100
for j=1; k=100, k=99, k=98 .... k=2, k=1; x is now 200
.............................................
.............................................
for j=98; k=100, k=99, k=98 .... k=2, k=1; x is now 9900
for j=99; k=100, k=99, k=98 .... k=2, k=1; x is now 10000
The result would have been the same, had the code been modified as:
for(int j = 0; j < 100; j++) {
for(int k = 0; k < 100; k++) // NOTE: reversal of k here.
{
x++;
}
}
The inner k loop is just being executed in reverse order (from 100 to 0) just to confuse the newbies.
You just have to understand how many times each loop executes.
Note that first loop runs 100 times. So, everything inside it will repeat 100 times. The inner loop also runs 100 times. So x++ will execute 100 * 100 = 10000 times.
for (int j = 0; j < 100; j++) // 100 times
{
for (int k = 100; k > 0; k--) // 100 * 100 times
{
x++; // 100 * 100 times
}
}
System.out.println("x = " + x); // This should print 10000 (assuming that x is zero initially)
for(int j = 0; j < 100; j++) //j -> 0~99 =>total=100
{
for(int k = 100; k > 0; k--) //k -> 100~1 =>total=1oo
{
x++;
}
}
System.out.println(x); //should print 10000 bcz of 100*100

Can you help me to calculate time complexity of this algorithm?

public static void complexityexample(int n) {
int count = 0;
int k = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
count++;
}
k *= 2;
for (int t = 0; t < n; t++) {
count++;
}
System.out.println(count);
}
}
Can anyone write me the answer?
for example , I know that nuber of operations in the for loop is 2N+2,
and number of operations in count++; is N
but what for the other parts.
Time complexity is O(2n). The bottle neck is :
for(int j = 0; j < k; j++){
count++;
}
Since k increases exponentially every iteration of i.
In the i'th iteration, k = 2i-1. This means iterating all values from j to k is O(k) = O(2i).
Now, sum it all up for all iterations:
20 + 21 + 22 + ... + 2n-1 = 2n - 1
Where last equality comes from sum of geometric series
Note that the next inner loop:
for (int t = 0; t < n; t++) {
is not influencing the time complexity (in terms of asymptotic notation), since it adds O(n) time for each iteration of i, and this gets quickly suppressed by the exponential behavior of the first inner loop.
If you want to count the value of count at the end, it is the summation of the first inner loop, which as said is (2n)-1, and the second inner loop, which is sum{n | for each i} = n2.
(2^n)+(n*n)
as them main loop is
for (int i = 0; i < n; i++) {
2^n from :
for (int j = 0; j < k; j++) {
count++;
}
and n*n from:
for (int t = 0; t < n; t++) {
count++;
}
1st row ) 1 operation.
2st row ) 2 operations.
3rd row ) 1+n+1+n = 2N+2.
4 ) 2N+2
5)N
7) N
9)2N+2
10)N
13)1
Is this right.
And after all math calculations the final result is : 14N^2 + 22N + 11 - operations.
A precise methodology using Sigma notation would be:
Empirically verified:
When n = 10, number of overall iterations is 1123.
When n = 25, number of overall iterations is 33555056.
When n = 50, it took for ever to execute (I had to change variables type from int to long).
Indeed, this non polynomial algorithm is expensive.

How can I remove a modulo out of my math operation?

My prof does not like the use of modulo since it's not efficient enough, but I'm not sure how else I can get the same answer using a logic operator or something. Can someone help me out with how I can do this?
j = (j + 1) % a.length;
This should do the trick.
int k = a.length;
int d = (j+1)/k;
j = (j+1) - d*k
The only way I can see of doing this without a modulo is still not great:
j = (++j < a.length)? j : (j - a.length);
Alternately, for more readability:
j++;
j = (j < a.length)? j : (j - a.length);
or
j++;
if (j >= a.length) {
j -= a.length;
}
Also, I'm not entirely sure about how Java does with loop prediction, but at least in C, the following would be slightly better for speed, if less readable, since the general assumption is that the argument to the if statement will be true, and j < a.length more often than not (Unless a.length <= 2, which seems unlikely.)
j++;
if(j < a.length) {
}
else {
j -= a.length;
}
If the initial value of j is outside the range 0 to a.length (inclusive-exclusive), then the only solutions either use a modulus or division, which, being the same operation, are the same speed, or a loop of subtraction, which will essentially accomplish the same thing as modulus on a very old processor, which is slower than the built in operation for modulus on any current processor I know about.
You could do this:
j = j + 1;
if (j >= a.length) {
j = j - a.length; // assumes j was less than length before increment
}
#ajp suggests another solution that actually would work ok.
j = j + 1;
if (j >= a.length) { // assumes j was less than length before increment
j = 0;
}
If I was writing the code, id write it this way, just in case. It has very little additional overhead and removes the "assumes"
j = j + 1;
while (j >= a.length) {
j = j - a.length;
}
Of course, the % would be a good way to do it too. Unless one is your professor.
This could be faster or slower than a divide/modulo depending on the cost of a jump (and any effect that has on the instruction pipeline/lookahead) and the efficiency of the integer division instructions.
Old processors would likely do better with the jump. More modern ones with the divide.
Think of what you are doing here. You are essentially saying:
if j + 1 is smaller than a.length, set j to j + 1
otherwise, we set j to a value smaller than a.length
This pseudocode should give you a very clear hint to the solution.

Categories