What will be the time complexity of the following algorithm? - algorithm

for(i=0;i< m; i++)
{
for(j=i+1; j < m; j++)
{
for(k=0; k < n;k++)
{
for(l=0;l< n;l++)
{if(condition) do something}
}
}
}

In details:
The two first loops will result in (m-1) + (m-2) + (m-3) + ... + 1 repetitions, which is equal to m*(m-1)/2. As for the second two loops, they basically run from 0 to n-1 so they need n^2 iterations.
As you have no clue whether the condition will be fulfilled or not, then you take the worst case, which is it being always fulfilled.
Then the number of iterations is:
m*(m+1)/2*n^2*NumberOfIterations(Something)
In O notation, the constants and lower degrees are not necessary, so the complexity is:
O(m^2*n^2)*O(Something)

for(i=0;i< m; i++)
{
for(j=i+1; j < m; j++)
{
The inner loop will run ((m-1) + (m-2) + ... 1) times
= 1 + 2 + 3 + ...m-1
= m * (m - 1) / 2
for(k=0; k < n;k++)
{
for(l=0;l< n;l++)
{
In this case, the inner loop clearly runs n * n times
So clearly, the number of iterations is exactly
(m * (m - 1) / 2) * (n * n)
= O(m^2 * n^2)
Obviously, this assumes that
if(condition) do something
runs in constant time.

Looks like O(m^2 n^2) to me, assuming the "something" is constant-time.
Although the j loop starts from a different point with each step, the combined effect of the i and j loops is still an m^2 factor.
Evaluating the unstated condition itself would normally be (at least) a constant time operation, so certainly the loop cannot be faster than O(m^2 n^2) - unless, of course, the "something" includes a break, goto, exception throw or whatever that exits out of one or more of the loops early.
All bets are off if, for any reason, either n or m isn't constant throughout.

I assume the time complexity of "do something" is O(S).
Let's start with the most inner loop: It's time complexity is O(n*S) because it does something n times. The loop which wraps the most inner loop has a time complexity of O(n)O(nS)=O(n^2*S) because it does the inner loop n times.
The loop whcih wraps the second most inner loop has a time complexity of O(m-i)*O(n^2*S) because it does an O(n^2*S) operation m-i times.
Now for the harder part: for each i in the range 0...m-1 we do an (m-i)*O(n^2*S) operation. How long does it take? (1 + 2 + 3 + ... + m)*O(n^2*S).
But (1 + 2 + ... + m) is the sum of an arithmetic sequence. Therefore the sum equals to m*(m-1)/2=O(m^2).
Conclusion: We do an O(n^2*S) operation about m^2 times. The time complexity of the whole thing is O(m^2*n^2*S)

O(m^2*n^2*(compexity of something)). If condition and something are executed in constant time then O(m^2*n^2).

O(m²*n²) *complexity of "something"

Related

Time complexity of the inner loop

Can someone help me with calculating the time complexity of the inner loop? As far as I understand, the outer one will be O(n). But I have no idea how to calculate what happens inside the second one.
for (int i = 2; i < n; i++) {
for (int j = 2; i * j < n; j++) {
}
For every iteration of "outer loop", inner loop runs n/i times
So, total complexity of this will be given by:
n/2 + n/3 + n/4 + ...
= n * (1/2 + 1/3 + 1/4 ...)
For the right term above, upper bound is ln(n)
Hence, complexity of this code is O(n log n).
The inner loop runs from 2 up to but not including n/i times. You can express it as n/i - 2.
If we run the inner loop n - 2 times (since that's the number of times the outer loop runs), we get the following summation:
(n/2 - 2) + (n/3 - 2) + ... + (3 - 2)
I have a hunch but can't remember 100% that this series sums up to log_e(n) * n or similar. So in terms of time complexity, this becomes O(log n * n).
The loop exits as soon as i * j ≥ n, i.e. when j = ceiling(n / i) ~ n / i. As it starts from j=2, the number of iterations is ceiling(n / i) - 1.

Time complexity of nested loop where the second loop iterates only for the last iteration of the above loop

Imagine a scenario where the second loop is iterated once for each iteration of n except the last one where it is iterated m times:
// n and m are two different variables.
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(i!=(n-1)) break;
// O(1) code here.
}
}
What would be the time complexity of this? Is it O(n*m), O(n+m) or something else?
EDIT: original answer was wrong based on a misread.
This is O(n + m) because for n - 1 iterations of the outermost loop, a constant amount of work is done: it starts the inner loop and aborts on the first iteration. For the last iteration of the outermost loop, the innermost loop iterates m times, doing a constant amount of work each iteration. So, we have (n - 1) * x + 1 * (m * y) total steps, where x and y are some constants. And we know that (n - 1) * x + 1 * (m * y) = O(n + m) since we can drop the constant factors on our independent variables n and m.

Why does this code has a time complexity of O(N*N)? [duplicate]

This question already has answers here:
How can I find the time complexity of an algorithm?
(10 answers)
Closed 5 years ago.
int a = 0;
for (i = 0; i < N; i++) {
for (j = N; j > i; j--) {
a = a + i + j;
}
}
Why does this code has time complexity of O(NN) ? Are all nested loops with n,m,q,.... bounds have a complexity of O(nm*q....) even though few iterations of the loops will not happen?
The reason for this is that constant factors are ignored in Big-O notation.
Your outer loop runs N times, while the inner loop runs on average N/2 times for each of the outer iterations.
This gives O(N * 1/2 * N) executions of the statements within the inner loop. Since we ignore constant factors, we end up with O(N * N) which is O(N^2).
The reason for omitting constants is simple: Big-O notation is about what happens when N is big. If you look at it this way - O((N^2)/2) - you see that increasing N has much more influence in the term, than whether or not we omit the division by two.
I wouldn't say all nested loops have that complexity, but this one certainly does. The number of iterations through the inner loop is something like this (there might be an off-by-one error):
i = 0: N times
i = 1: N - 1 times
i = 2: N - 2 times
. . .
i = N-1: 1 times
i = N: 0 times
Let's count the total number of times the innermost code is called. In this case, you can figure this out arithmetically. The innermost code is executed about N * (N + 1) / 2 times (this is the sum of elements from 1 to N). This simplifies to 0.5 * N^2 + 0.5 * N and that has a complexity of N^2.

how i can find the time complexity of the above code

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 !

Tricky Big-O complexity

public void foo(int n, int m) {
int i = m;
while (i > 100) {
i = i / 3;
}
for (int k = i ; k >= 0; k--) {
for (int j = 1; j < n; j *= 2) {
System.out.print(k + "\t" + j);
}
System.out.println();
}
}
I figured the complexity would be O(logn).
That is as a product of the inner loop, the outer loop -- will never be executed more than 100 times, so it can be omitted.
What I'm not sure about is the while clause, should it be incorporated into the Big-O complexity? For very large i values it could make an impact, or arithmetic operations, doesn't matter on what scale, count as basic operations and can be omitted?
The while loop is O(log m) because you keep dividing m by 3 until it is below or equal to 100.
Since 100 is a constant in your case, it can be ignored, yes.
The inner loop is O(log n) as you said, because you multiply j by 2 until it exceeds n.
Therefore the total complexity is O(log n + log m).
or arithmetic operations, doesn't matter on what scale, count as basic operations and can be omitted?
Arithmetic operations can usually be omitted, yes. However, it also depends on the language. This looks like Java and it looks like you're using primitive types. In this case it's ok to consider arithmetic operations O(1), yes. But if you use big integers for example, that's not really ok anymore, as addition and multiplication are no longer O(1).
The complexity is O(log m + log n).
The while loop executes log3(m) times - a constant (log3(100)). The outer for loop executes a constant number of times (around 100), and the inner loop executes log2(n) times.
The while loop divides the value of m by a factor of 3, therefore the number of such operations will be log(base 3) m
For the for loops you could think of the number of operations as 2 summations -
summation (k = 0 to i) [ summation (j = 0 to lg n) (1)]
summation (k = 0 to i) [lg n + 1]
(lg n + 1) ( i + 1) will be total number of operations, of which the log term dominates.
That's why the complexity is O(log (base3) m + lg n)
Here the lg refers to log to base 2

Resources