This question already has answers here:
Running time complexity of double for-loops
(3 answers)
Closed 7 years ago.
Take N=5 as one example. The number of operations in the two loops is 5 + 4 + 3 + 2 + 1 = 15. Which seems to be N + N-1 + N-2 + N-3 + ... + 1. Can I say this is N^2?
for(int i=0; i<N; i++){
for(int j=i; j<N; j++){
...//
}
}
As mentioned the complexity of this is (most likely) O(N2), but only if the complexity in the loop is O(1). If not, the overall complexity could be different.
Also there could be a worst case, if there is a break-condition in the loop.
Example:
for(int i = 0; i < N; i++){
for(int j = i; j < N; j++){
if(N % 2 == 1)
break;
}
}
The best case is Θ(N) (all odd N), the worst case is Θ(N2) (for all even N).
If N = 2n + 1 (for any positive integer n, i.e. N is odd), the condition N % 2 == 1 will be true. So the inner loop will be exited after the first run. So the complexity is O(N ⋅ 1) = O(N).
If N = 2⋅n (for any positive integer n, i.e. N is even), the condition is never true, so the inner loop is completely executed. So the complexity is
O(N + N-1 + ... + 2 + 1) = O(N⋅(N+1)/2) = O(N²).
If the code in the inner loop needs more than O(1), the overall complexity will not fit into O(N²).
It is N(N+1)/2 which in Big-O notation still increases as N^2 but fairly good as N^2 goes.
Using Sigma notation, you obtain this:
Related
What is the time complexity for this piece of code?
for(int = n; i > 0; i--){
for(int j = 1; j < n; j*=2){
for(int k = 0; k < j; k++) {
...//constant number C of operations
}
}
}
I find that the two innerloops creates the time complexity of O(n*logn)(?). Together with outer loop this results in time complexity of O(n^2 * logn) for the whole piece of code (?).
According to the answer, the result should be O(n^2) and not O(n^2 * logn).
Can someone help me understand why?
You're right that the first for loop runs O(N) times. Lets look at the inner two.
So looking at j it will be 1,2,4,8,16 .. n, this means the inner k loop will run
1 + 2 + 4 .. + n
times, or written another way
2^0 + 2^1 + 2^2 ... 2^log(n)
you can look up this summation and find its O(2^log(n + 1))) = O(n).
So if we multiply the two inner and outer loops we would get O(n^2)
This is the loop structure :
for (int i = 1 ; i < n ; i++) {
for (int j = 0 ; j < n ; j += i) {
// do stuff
}
}
My guess was O(nlogn) as it clearly cannot be O(n^2) since the increment in j is increasing and it clearly cannot be O(n sqrt(n)) since the increment is not that high. But I have no idea how to prove it formally.
Each time complexity of the inner loop is based on the value of i is n/i. Hence, total time would be n + n/2 + n/3 + ... + n/n = n(1+1/2+1/3+...+1/n).
As we know 1+1/2+1/3+...+1/n is a harmonic sereis and asymptotically is log(n). Hence, the algorithm is run in O(nlog(n)).
This question already has answers here:
Time complexity for dependant nested for loop?
(3 answers)
Closed 5 years ago.
Suppose I have a code with two for-loops:
int sum = 0;
for (int i = 1; i < N; i *= 2)
for(int j = 0; j < i; j++)
sum++;
How would I find the worst-case time complexity of this code? I've looked at many tutorials on finding time complexity and I understood them. But this one just seems a bit different from those in the tutorials.
Lets do simple maths.
Value of i in each iteration goes as 1,2,4,8... (log N + 1) terms. In each iteration, the inner loop goes i times. Adding up the values of i
T(N) = 1 + 2 + ... + (log N + 1) terms i.e. GP with a = 1 and r = 2 and n = (log N + 1)
T(N) = a[(rn-1)/(r-1)]
= 1[(2(logN+1) - 1)/(2-1)]
= 2N - 1
= O(N)
So the complexity is O(N) in all scenarios.
First consider a simpler case when N=2^k+1 for some integer k. In this case the outer loop has k iterations and the overall number of operations is
T(N) = 1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 = 2N - 3.
So the worst case complexity is at least O(2N - 3) = O(N).
Now suppose 2^k + 1 < N <= 2^(k+1) for some k. Then
T(N) = 1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 < 2N = O(N)
Therefore T(N) = O(N).
for(i=0; i<n; i++) // time complexity n+1
{
k=1; // time complexity n
while(k<=n) // time complexity n*(n+1)
{
for(j=0; j<k; j++) // time complexity ??
printf("the sum of %d and %d is: %d\n",j,k,j+k); time complexity ??
k++;
}
What is the time complexity of the above code? I stuck in the second (for) and i don't know how to find the time complexity because j is less than k and not less than n.
I always having problems related to time complexity, do you guys got some good article on it?
especially about the step count and loops.
From the question :
because j is less than k and not less than n.
This is just plain wrong, and I guess that's the assumption that got you stuck. We know what values k can take. In your code, it ranges from 1 to n (included). Thus, if j is less than k, it is also less than n.
From the comments :
i know the the only input is n but in the second for depends on k an not in n .
If a variable depends on anything, it's on the input. j depends on k that itself depends on n, which means j depends on n.
However, this is not enough to deduce the complexity. In the end, what you need to know is how many times printf is called.
The outer for loop is executed n times no matter what. We can factor this out.
The number of executions of the inner for loop depends on k, which is modified within the while loop. We know k takes every value from 1 to n exactly once. That means the inner for loop will first be executed once, then twice, then three times and so on, up until n times.
Thus, discarding the outer for loop, printf is called 1+2+3+...+n times. That sum is very well known and easy to calculate : 1+2+3+...+n = n*(n+1)/2 = (n^2 + n)/2.
Finally, the total number of calls to printf is n * (n^2 + n)/2 = n^3/2 + n^2/2 = O(n^3). That's your time complexity.
A final note about this kind of codes. Once you see the same patterns a few times, you quickly start to recognize the kind of complexity involved. Then, when you see that kind of nested loops with dependent variables, you immediately know that the complexity for each loop is linear.
For instance, in the following, f is called n*(n+1)*(n+2)/6 = O(n^3) times.
for (i = 1; i <= n; ++i) {
for (j = 1; j <= i; ++j) {
for (k = 1; k <= j; ++k) {
f();
}
}
}
First, simplify the code to show the main loops. So, we have a structure of:
for(int i = 0; i < n; i++) {
for(int k = 1; k <= n; k++) {
for(int j = 0; j < k; j++) {
}
}
}
The outer-loops run n * n times but there's not much you can do with this information because the complexity of the inner-loop changes based on which iteration of the outer-loop you're on, so it's not as simple as calculating the number of times the outer loops run and multiplying by some other value.
Instead, I would find it easier to start with the inner-loop, and then add the outer-loops from the inner-most to outer-most.
The complexity of the inner-most loop is k.
With the middle loop, it's the sum of k (the complexity above) where k = 1 to n. So 1 + 2 + ... + n = (n^2 + n) / 2.
With the outer loop, it's done n times so another multiplication by n. So n * (n^2 + n) / 2.
After simplifying, we get a total of O(n^3)
The time complexity for the above code is : n x n x n = n^3 + 1+ 1 = n^3 + 2 for the 3 loops plus the two constants. Since n^3 carries the heaviest growing rate the constant values can be ignored, so the Time complexity would be n^3.
Note: Take each loop as (n) and to obtained the total time, multiple the (n) values in each loop.
Hope this will help !
What is the complexity given for the following problem is O(n). Shouldn't it be
O(n^2)? That is because the outer loop is O(n) and inner is also O(n), therefore n*n = O(n^2)?
The answer sheet of this question states that the answer is O(n). How is that possible?
public static void q1d(int n) {
int count = 0;
for (int i = 0; i < n; i++) {
count++;
for (int j = 0; j < n; j++) {
count++;
}
}
}
The complexity for the following problem is O(n^2), how can you obtain that? Can someone please elaborate?
public static void q1E(int n) {
int count = 0;
for (int i = 0; i < n; i++) {
count++;
for (int j = 0; j < n/2; j++) {
count++;
}
}
}
Thanks
The first example is O(n^2), so it seems they've made a mistake. To calculate (informally) the second example, we can do n * (n/2) = (n^2)/2 = O(n^2). If this doesn't make sense, you need to go and brush up what the meaning of something being O(n^k) is.
The complexity of both code is O(n*n)
FIRST
The outer loop runs n times and the inner loop varies from 0 to n-1 times
so
total = 1 + 2 + 3 + 4 ... + n
which if you add the arithmetic progression is n * ( n + 1 ) / 2 is O(n*n)
SECOND
The outer loop runs n times and the inner loop varies from 0 to n-1/2 times
so
total = 1 + 1/2 + 3/2 + 4/2 ... + n/2
which if you add the arithmetic progression is n * ( n + 1 ) / 4 is also O(n*n)
First case is definitely O(n^2)
The second is O(n^2) as well because you omit constants when calculate big O
Your answer sheet is wrong, the first algorithm is clearly O(n^2).
Big-Oh notation is "worst case" so when calculating the Big-Oh value, we generally ignore multiplications / divisions by constants.
That being said, your second example is also O(n^2) in the worst case because, although the inner loop is "only" 1/2 n, the n is the clear bounding factor. In practice the second algorithm will be less than O(n^2) operations -- but Big-Oh is intended to be a "worst case" (ie. maximal bounding) measurement, so the exact number of operations is ignored in favor of focusing on how the algorithm behaves as n approaches infinity.
Both are O(n^2). Your answer is wrong. Or you may have written the question incorrectly.