Big(o) notation logn or n? - big-o

for(int i = 1; i < N; i = 2*i){
for(j=0; j<i; j++){
}
}
so I just learned that a logN for loop is one that either divides or multiplies in a statement, which the outerloop is doing. However, because the inner loop is incrementing with addition, and that linear time is a higher complexity than logN, would this for loop be considered O(n)?

The inner function is O(n) because it runs in linear time, and the outer function is O(log n) because i is multiplied by 2 every iteration. So to answer you question, yes the inner loop would be considered O(n) because j++ runs in linear time. But since O(n) is higher complexity than O(log n), then O(n) takes more precedence and the overall run time will be O(n).

Related

Time complexity of this code confusing me

I'm struggling to understand the concepts of calculating time complexity. I have this code in C, why does the time complexity is O(n) and not O(n log n)?
The first loop is running for maximum of 3 iteration, the outer for loop is in logarithmic complexity and each iteration of it doing linear time.
int f2 (int n)
{
int j, k, cnt=0;
do
{
++n;
} while (n%3);
for (j=n; j>0; j/=3)
{
k=j;
while (k>0)
{
cnt++;
k-=3;
}
}
return cnt;
}
Why do we neglecting the log time?
T = (n+n/3+n/9+...+1)
3*T - T = 3*n-1
T = 1.5*n-0.5
it's O(n)
It is a common beginner's mistake to reason as follows:
the outer loop follows a decreasing geometric progression, so it iteratess O(log n) times.
the inner loop follows an arithmetic progression, so its complexity is O(n).
hence the global complexity is O(n+n+n+...)=O(n log n).
The mistake is due to the lack of rigor in the notation. The correct approach is
the outer loop follows a decreasing geometric progression, so it iterates O(log n) time.
the inner loop follows an arithmetic progression, so its complexity is O(j) (not O(n) !), where j decreases geometrically.
hence the global complexity is O(n+n/3+n/9+...)=O(n).
The time complexity of you program is O(n).
Because the total number of calculations is : log(n)/log(3) + 2 * (n/3 + n/9 + n/27 + ... < log(n) + n/2 < 2*n

Asymptotic Growth of Run Time of function with three nested for loops

I have pseudo code for a function (below). I understand that if each of i, j and k were 1 then worst case run time would be O(n^3). I am struggling to understand the impact of n/2 though - if any - on run time. Any guidance would be great.
for i=n/2; i < n; increase i by 1
for j=1; j < n/2; increase j by 1
for k = 1; k < n; increase k by k*2
Execute a Statement
Your understanding is not correct
k is increased by k*2 which leads to logarithmic time, the complexity is actually O(n^2 * log n)
The O(n/2) = O(n), therefore the n/2 does not have any impact on asymptotic growth.
If you are not sure, the general approach is to count it as precise as possible and then remove the constants.
for i will be execute n/2 times, the for j also n/2 times and k will be executed log n times.
n/2 * n/2 * log n = (n^2/4) * log n. You can remove constants, so O(n^2 * log)
The worst case time complexity is not O(N^3)
Check the innermost for loop. K increases by K * 2
That means, the innermost for loop will take O(lgN) time
Other two outer loops would take O(N) time each and N/2 would not have any effect on the asymptotic growth of run time.
So, the overall time complexity would be O(N^2 * lgN)

What is the time complexity and space complexity of following code

I want to know the time complexity of following piece of code
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
printf("hi")
}
}
Time complexity in loop
http://www.geeksforgeeks.org/analysis-of-algorithms-set-4-analysis-of-loops/
http://www.geeksforgeeks.org/analysis-of-algorithms-set-4-analysis-of-loops/
i think following link is used full for this problem :)
Time complexity is nothing but the number of instructions executed in your program. Now, in your program you have two loops. Outer loop will iterate i=0 to i=N-1, which is total of N instructions that is O(N). Since you also have a inner loop which will again iterate from j=i+1 to j=N-1 for each i.
Hence, time complexity will be O(N^2).
At each iteration of the inner loop work done is a follows
n
n-1
n-2
....
...
1
So total work done will be n+(n-1)+(n-2)+...+...+1, which turn out to be the sum of n natural numbers i.e n*(n+1)/2 so time complexity is O(n^2). As no auxiliary space is used so space complexity is O(1)

Why is the Big-O complexity of this algorithm O(n^2)?

I know the big-O complexity of this algorithm is O(n^2), but I cannot understand why.
int sum = 0;
int i = 1; j = n * n;
while (i++ < j--)
sum++;
Even though we set j = n * n at the beginning, we increment i and decrement j during each iteration, so shouldn't the resulting number of iterations be a lot less than n*n?
During every iteration you increment i and decrement j which is equivalent to just incrementing i by 2. Therefore, total number of iterations is n^2 / 2 and that is still O(n^2).
big-O complexity ignores coefficients. For example: O(n), O(2n), and O(1000n) are all the same O(n) running time. Likewise, O(n^2) and O(0.5n^2) are both O(n^2) running time.
In your situation, you're essentially incrementing your loop counter by 2 each time through your loop (since j-- has the same effect as i++). So your running time is O(0.5n^2), but that's the same as O(n^2) when you remove the coefficient.
You will have exactly n*n/2 loop iterations (or (n*n-1)/2 if n is odd).
In the big O notation we have O((n*n-1)/2) = O(n*n/2) = O(n*n) because constant factors "don't count".
Your algorithm is equivalent to
while (i += 2 < n*n)
...
which is O(n^2/2) which is the same to O(n^2) because big O complexity does not care about constants.
Let m be the number of iterations taken. Then,
i+m = n^2 - m
which gives,
m = (n^2-i)/2
In Big-O notation, this implies a complexity of O(n^2).
Yes, this algorithm is O(n^2).
To calculate complexity, we have a table the complexities:
O(1)
O(log n)
O(n)
O(n log n)
O(n²)
O(n^a)
O(a^n)
O(n!)
Each row represent a set of algorithms. A set of algorithms that is in O(1), too it is in O(n), and O(n^2), etc. But not at reverse. So, your algorithm realize n*n/2 sentences.
O(n) < O(nlogn) < O(n*n/2) < O(n²)
So, the set of algorithms that include the complexity of your algorithm, is O(n²), because O(n) and O(nlogn) are smaller.
For example:
To n = 100, sum = 5000. => 100 O(n) < 200 O(n·logn) < 5000 (n*n/2) < 10000(n^2)
I'm sorry for my english.
Even though we set j = n * n at the beginning, we increment i and decrement j during each iteration, so shouldn't the resulting number of iterations be a lot less than n*n?
Yes! That's why it's O(n^2). By the same logic, it's a lot less than n * n * n, which makes it O(n^3). It's even O(6^n), by similar logic.
big-O gives you information about upper bounds.
I believe you are trying to ask why the complexity is theta(n) or omega(n), but if you're just trying to understand what big-O is, you really need to understand that it gives upper bounds on functions first and foremost.

Are two (non nested) "for loops" iterating over the same size array of n = O(2n)

for example if we have
public void search(){
for (int i=0; i<n; i++){
.............
}
for (int j=0; j<n; j++){
.............
}
}
would search() be O(n) + O(n) = O(2n) ?
Yes, the time is linear in n, but because constant factors are not interesting in O-notation, you can still write O(n). Even if you had 10 consecutive for-loops from 1 to n, it would still be O(n). Constant factors are dropped.
Edit (answer to your comment):
If i, n and k are independent, yes, it would be O(k + (n-i)).
But you could simplify it if you for example know that k = O(n). (e.g. k ≈ n/2). Then you could write it as O(n - i) (because in O(2n - i), the 2 is dropped).
If i and k are both linearly dependent on n, it would even be O(n).
Yes, this is O(2n) which is equivalent to saying it is O(n), the coefficient doesn't matter really.
Big-O notation expresses time or space complexity. It does not measure time or space directly, it measures how the change in number of elements impacts time or space. While two loops are certainly slower than one, they both scale exactly the same: in direct proportion to n. That is what O(n) means.
(Slight simplification here, it does not account for why O(n^2 + n) = O(n^2), for example, but it should suffice for the matter at hand.)

Resources