Complexity of java code with nested for loops - java

I am trying to analyze this code below. I wish to calculate both the complexity and the number of operations / iterations (which leads to complexity). My guess is that the complexity is O(n^2), since I have nested for loops. However, inside the inner loop, the values are switching, replacing places. Doesn't this operation makes the algorithm repeat things more than once and hence it's more than O(n^2), or is it only possible with a while loop ? How do I find the exact number of iterations / operations done ?
for (int i = 0; i < b.Length; i++)
{
for (int j = i + 1; j < b.Length; j++)
{
if (b[i] > b[j])
{
t = b[i];
b[i] = b[j];
b[j] = t;
}
}
}

The outer loop has b.length iterations. Let's call that n.
The inner loop has n - i - 1 iterations.
The total number of iterations of the inner loop is
(n - 1) + (n - 2) + ... + 1 = n * (n -1) / 2 = O(n^2).
Each iteration of the inner loop does constant work - at most 1 condition + 3 assignments - so the total running time is O(n^2).
The exact number of operations depends on the input, since the input determines how many times the condition is true.

The number of loops is controlled by b.length which is a constant and the index variables i and j. As long as you don't meddle with i an j inside the loop, the complexity remains the same.

Related

What is the Big-O complexity of nested for loops of increasing length

I'm new to the Big O notation and I am a little bit confused on how the following code plays into the Big O notation. In this situation n is just the length of an array and as you can see the two inner for loops are iterating through n^2 and n * 4. How does that play into the Big O notation? At first glance I thought it was n^3 however I am unsure.
for (int i=0; i < n; i++) {
for (int j=0; j < n*n; j++)
sum += data[i] * data[j];
for (int j=0; j < 4*n; j++)
sum += data[i] + data[j];
}
O(n * (O(c1 * n^2) + O(c2 * 4 * n))) =
O(n * (O(n^2) + O(n)) =
O(n * O(n^2)) =
O(n ^ 3)
Because sum (+), assignment (=), multiplication (*) and array access ([i]) cost constant.
So you are right.
The first loop iterates n times. For each iteration of the first loop second loop iterates n*n times. Therefore the total number of iterations of the second loop is n*(n*n). Furthermore for each iteration of the first loop third loop iterates 4*n times. Therefore the total number of iterations of the third loop is n*(4*n).
Hence complexity is O(n*n*n + n*4*n) -> O(n^3 + n^2) -> O(n^3).
You are right!!

Facing a problem analyzing this code segment to find BigO

for (int i = 1; i <= Math.pow(2, n); i = i * 2) {
for (int j = 0; j <= Math.log(i); j++) {
sum = i + j;
System.out.println(sum); // we would like to print the sum..
}
}
How can i count the number of primitive operation my code has?
Analyzing the first loop, you can see that the limit is 2^n but you can see that the increment step is i = i x 2, so how many multiplications until you reach the limit? The answer is obviously n.
The inner loop, in the worst case how many iterations will perform? Since it depends on the maximum value that the first loop variable (i) will ever take, then it is the natural logarithm of that value, in other words, log(2^n).
Summarizing, the total complexity of the algorithm is O(n * log(2^n)) which simplifies to O(n*n) by taking out the exponent (as promptly suggested by #Andreas).

Calculating Big O complexity of these algorithms?

I am trying to figure out the Big O notation of the following 2 algorithms below but am having trouble.
The first one is:
public static int fragment3 (int n){
int sum = 0;
for (int i = 1; i <= n*n; i *= 4)
for (int j = 0; j < i*i; j++)
sum++;
return sum;
} //end fragment 3
The answer should be O(n^4). When I try to do it myself this is what I get:
I look at the first for loop and think it runs n^2 logn times. Then for the inner for loop, it runs n times + the run time of the outer loop which is n^3 logn times. I know this is wrong but just don't get it.
For the code fragment below, the answer is O(n^9).
public static int fragment6(int n) {
int sum = 0;
for(int i=0; i < n*n*n; i++) {
if(i%100 == 0) {
for(int j=0; j < i*i; j += 10)
sum++;
} // if
else {
for(int k=0; k <= i; k++)
sum++;
} // else
} // outer loop
return sum;
} // fragment 6
When I attempt it I get: n^3 for the outer for loop. for the if statement I get n, for the second for loop I get n + the other for loop and if statement, making it n^5. Finally, I get n for the final for loop and everything adds up to O(n^6).
What am I doing wrong and what is the correct way to get its O(n^9) complexity?
For the first one.
Let's look at the inner loop..
At the first iteration of the outer loop (i=1) it runs 1 time. At the second iteration (i=4) it runs 16 (4*4) times. At the third iteration (i=16) it runs 256 (16*16) times. In general, at the (k+1)-th iteration of the outer loop inner loop runs times, as at that iteration. So the total number of iterations will be
Now, how many numbers in that sum we will have? To determine that we should have a look at the outer loop. In it i grows as , until it reaches . So the total number of iterations is .
This means that the total number of runs of inner loop is
(by dropping all the numbers from the sum but the last one).
Now we know, that the inner loop runs at least times, so we are not faster than O(n^4).
Now,
Solving for N,
where C is a constant, so we're not slower than O(n^4).
Your approach to computing big-O is flat-out wrong, and you've made computation errors.
In some common cases you can take the worst case number of iterations and multiply them together, but this isn't a sound method and fails for cases like this:
for (i = 1; i < n; i *= 2) {
for (j = 0; j < i; j++) {
sum++;
}
}
Here, the outer loop runs log_2(n) times, and the inner loop worst case is n iterations. So the wrong method that you're using will tell you that the complexity of this code is O(n log n).
The correct method is to count accurately the number of iterations, and approximate at the end only. The number of iterations is actually:
1 + 2 + 4 + 8 + ... + 2^k
where 2^k is the largest power of two less than n. This sum is 2^(k+1) - 1, which is less than 2n. So the accurate complexity is O(n).
Applying this idea to your first example:
for (int i = 1; i <= n*n; i *= 4)
for (int j = 0; j < i*i; j++)
sum++
i takes the values 4^0, 4^1, 4^2, ..., 4^k where 4^k is the largest power of 4 less than or equal to n^2.
The inner loop executes i^2 times for a given value of i.
So overall, the inner sum++ is executed this many times:
(4^0)^2 + (4^1)^2 + ... + (4^k)^2
= 2^0 + 4^2 + ... + 4^2k
= 16^0 + 16^1 + ... + 16^k
= (16^k - 1) / 15
Now by definition of k we have n^2/4 < 4^k <= n^2. So n^4/16 < 4^2k <= n^4, and since 16^k = 4^2k, we get that the total number of times the inner loop is executed is O(16^k) = O(n^4).
The second example can be solved using a similar approach.
First case:
Last run of the inner-loop with i = n^2, runs for n^4. The outer-loop up to n^2, but using exponential growth. For summation the sum over all inner-loop runs but the last is less than the last run. So inner-loop is essentially contributing O(1).
Second case:
100 % n == 0 does not matter really in O thinking
else part does not matter, it is much less than main part
outer-loop runs from 0 to n^3 => n^3
inner-loop runs from 0 to n^6 => n^6
outer-loop times inner-loop => n^9

Big O of a for loop with a false condition

I just need some clarification or help on this Big O problem. I don't know if I'm explaining this correctly, but I noticed that the for loop has a false condition, so that means it won't loop at all. And my professor said it's possible to still determine the run time of the loops. So what I'm thinking is this:
1 + (n - 1 - n) * (n) = 1 + 1 * n = 1 + n = O(n)
Explanation: 1 is for the operation outside of the loop. (n - 1 - n) is the iteration of the outer loop and n is the iteration of the inner loop.
Note: I'm still learning Big O, so please correct me if any of my logic is wrong.
int total = 0;
for (int i = n; i < n - 1; i++) {
for (int j = 0; j < n; j++) {
total = total + 1
}
}
There shouldn't be any negative number in Big O analysis. It doesn't make sense for negative running time. Also, (n - 1 - n) is not just in order O(1). Your outer loop doesn't even go into one iteration. Thus, the time complexity for whatever statement in your loop doesn't matter.
To conclude, the running time is 1 + 1 = O(1).
Big O notation to describe the asymptotic behavior of functions. Basically, it tells you how fast a function grows or
declines
For example, when analyzing some algorithm, one might find that the time (or the number of steps) it takes to complete a problem of size n is given by
T(n) = 4 n^2 - 2 n + 2
If we ignore constants (which makes sense because those depend on the particular hardware the program is run on) and slower growing terms, we could say "T(n)" grows at the order of n^2 " and write:T(n) = O(n^2)
For the formal definition, suppose f(x) and g(x) are two functions defined on some subset of the real numbers. We write
f(x) = O(g(x))
(or f(x) = O(g(x)) for x -> infinity to be more precise) if and only if there exist constants N and C such that
|f(x)| <= C|g(x)| for all x>N
Intuitively, this means that f does not grow faster than g
If a is some real number, we write
f(x) = O(g(x)) for x->a
if and only if there exist constants d > 0 and C such that
|f(x)| <= C|g(x)| for all x with |x-a| < d
So for your case it would be O(n^2) as |f(x)| > C|g(x)|
Reference from http://web.mit.edu/16.070/www/lecture/big_o.pdf
int total = 0;
for (int i = n; i < n - 1; i++) { // --> n loop
for (int j = 0; j < n; j++) { // --> n loop
total = total + 1; // -- 1 time
}
}
}
Big O Notation gives an assumption when value is very big outer loop will run n times and inner loop is running n times
Assume n -> 100
than total n^2 10000 run times

Big O Notation of Java Nested Loops

I am aware of the various rates of Big O such as O(n^2) and O(n), and have no problem determining the Big O value of simple nested for loops such as the following.
for (int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
//Simple Statement
The following loop is clearly O(n^2), but how does one go about solving for Big O when the inner nested loop is dependent on the outer loop.
Example
for ( int i = 0; i < n; i++)
for (int j = n - 1; j >= i; j--)
//Simple Statement
would T(n) simply be n*(n-1-i) ?
Thanks in advance for the help!
It is still on the order of n^2. You only care about the most significant term. The second expression would look something line O(n^2 - an) where a is some sort of coefficient. All you really care about is the n^2.
The inner loop runs n + (n-1) + (n-2) + ... + 2 + 1 times. This is a Gaussian sum and equals n * (n + 1) / 2, or (n^2 + n) / 2, hence O(n^2).

Categories