For each of the procedures below, let T (n) be the running time. Find the order of T (n)
(i.e., find f(n) such that T (n) ∈ (f(n)).
Procedure Fum(int n):
for i from 1 to n do
y ← 1/i
x ← i
while x > 0 do
x ← x − y
end while
end for
I know how to find run times of simple functions but since this is a nested loop where the inner loop depends on a variable from the outer loop, I'm having trouble.
It should be 1+4+9+...+n^2 = n(n+1)(2n+1)/6, or simply O(n^3), for this case.
For each step in the for-loop, it will run i^2 times for the while. Given x=i;y=1/i;, it will take i^2 (as x=y*i^2) times for x to reach x<=0 by decreament step x=x-y.
For i, it will be 1,2,...,n, summing them up, you will get 1+4+9+...n^2 = n(n+1)(2n+1)/6.
First, lets consider the runtime of the inner loop:
We want to figure out how many times the inner loop runs, in terms of i.
That is, we want to solve for f(i) in x-f(i)y = 0. If we sub in x = i, and y = 1/i, we get f(i) = i^2.
We know the outer loop will run exactly n times, so then, we get the total number of times the inner loop will be run:
= 1 + 4 + 9 + ... + n^2
This sum is equal to n(n+1)(2n+1)/6, which is O(n^3)
Related
I have the following sequence of loops.
TripleLoop(int n)
for i <- 1 to n
for j <- 1 to n
for k <- j to n
do num <- j + i
return num
I know the two outer loops run "n" times.
Thus, we have n * n = n^2 for the two outer loops.
However, the third inner loop depends on the variable "j".
How do I begin to solve these types of nested dependent for-loops?
I'm not sure if I should multiply, or add the third inner loop to the two outer loops.
Can someone help me out here?
Well the inner loop (the one with k as iterator) is executed n-j+1 times, since it starts at j and ends with n.
The total number of steps the middle for loop thus performs is the sum of steps per iteration for j, so that means that the total number of times we run the body of the inner for loop is:
n
---
\ n * (n + 1)
/ n - j + 1 = -------------
--- 2
j=1
so after one iteration of the outer loop (the one with i as an iterator), we have n*(n+1)/2 steps.
In total, our algorithm will thus run the body of the inner loop for a total of n * n * (n+1)/2 times. Since the outer loop runs n times, and the number of steps in the body of that loop does not depend on the value of i itself.
If we consider the num <- j + 1 part to run in constant time (well strictly speaking summing up huge numbers can not be done in constant time), then this is thus an O(n3) algorithm.
if I have for example this simple code
for (i =1;i<=n;i++)
for (j=1 ;j<=i;j++)
count++;
for this line
for (i =1;i<=n;i++)
if I say that the time for 'i' to get a value is T then i will increase n+1 times since the condition is i<=n so the time for increasing i is (n+1)*T the condition will be asked n+1 times so lets say that the time needed to check the condition is T aswell then the total time for it to complete is (n+1)*T and i++ will be executed n times because when the condition is asked if i(in this case i is n+1) <=n it will be false so it wont increase i so the total time for executing this single loop would be (n+1)*T+(n+1)T+nT or (n+1+n+1+n)*T = (3n+2)T so big O for this case would be n
but I dont know how to calculate for the second loop I was thinking if it would be n[(3n+2)*T] and big O for this would be n^2 but I am not too sure if you dont understand what I am saying or if I made a mistake with first loop too if you can please explain in details how to I calculate it for that code .
First loop will execute n times, second loop i times, for each i from the outer loop. At the beginning, i=1, so the inner loop will have only one iteration, then i=2, i=3.. until i reaches the value n. Therefore, the total number of iterations is 1 + 2 + 3 + ... + n = n * (n + 1) / 2, which gives O(n^2).
1) i=s=1;
while(s<=n)
{
i++;
s=s+i;
}
2) for(int i=1;i<=n;i++)
for(int j=1;j<=n;j+=i)
cout<<"*";
3) j=1;
for(int i=1;i<=n;i++)
for(j=j*i;j<=n;j=j+i)
cout<<"*";
can someone explain me the time complexity of these three codes?
I know the answers but I can't understand how it came
1) To figure this out, we need to figure out how large s is on the x'th iteration of the loop. Then we'll know how many iterations occur until the condition s > n is reached.
On the x'th iteration, the variable i has value x + 1
And the variable s has value equal to the sum of i for all previous values. So, on that iteration, s has value equal to
sum_{y = 1 .. x} (y+1) = O(x^2)
This means that we have s = n on the x = O(\sqrt{n}) iteration. So that's the running time of the loop.
If you aren't sure about why the sum is O(x^2), I gave an answer to another question like this once here and the same technique applies. In this particular case you could also use an identity
sum_{y = 1 .. x} y = y choose 2 = (y+1)(y) / 2
This identity can be easily proved by induction on y.
2) Try to analyze how long the inner loop runs, as a function of i and n. Since we start at one, end at n, and count up by i, it runs n/i times. So the total time for the outer loop is
sum_{i = 1 .. n} n/i = n * sum_{i = 1 .. n} 1 / i = O(n log n)
The series sum_{i = 1 .. n} 1 / i is called the harmonic series. It is well-known that it converges to O(log n). I can't enclose here a simple proof. It can be proved using calculus though. This is a series you just have to know. If you want to see a simple proof, you can look on on wikipedia at the "comparison test". The proof there only shows the series is >= log n, but the same technique can be used to show it is <= O(log n) also.
3.) This looks like kind of a trick question. The inner loop is going to run once, but once it exits with j = n + 1, we can never reenter this loop, because no later line that runs will make j <= n again. We will run j = j * i many times, where i is a positive number. So j is going to end up at least as large as n!. For any significant value of n, this is going to cause an overflow. Ignoring that possibility, the code is going to perform O(n) operations in total.
I am trying to calculate the number of steps executed for the following nested loop specially for asymptotic growth. Based on the number of steps I will derive the Big O for this algorithm.
def get_multiples(list):
multiple = []
for o in list:
for i in list:
multiple.append(o*i)
return multiple
The way I have calculated is as follows (list consists of large number of elements = "n"):
Assignment statement (no. of steps = 1):
multiple = []
Nested Loops:
for o in list:
for i in list:
multiple.append(o*i)
In the outer loop the variable o is assigned n times. Each time the outer loop executes, first the variable i is assigned n times, then the variables are multiplied n times and finally the list is appended n times. Therefore the no. of steps = n*(n+n+n) = 3n2
Return statement (No. of steps = 1):
return multiple
Therefore the total no. of steps = 3n2 + 2
However the correct answer is 3n2 + n +2. Apparently the execution of the outer loop takes additional n steps which is not required for the inner loop.
Can somebody explain to me what did I miss ?
It does not make a difference to complexity since it will still be O(n2)
I think that the correct way to calculate the nested loop is as follows:
The number o is assigned n times.
the number i is assigned n2 times, o*i is calculated n2 times, the append function is called n2 times.
therefore n + n2 + n2 + n2 = 3n2 + n
add it to the rest and you get 3n2 + n + 2
def get_multiples(list):
multiple = [] // 1 STEP
for o in list: // Executed n times, so n STEPS
for i in list: // Executed n times for each value of o, so n*n STEPS
multiple.append(o*i) // 1 STEP to multiply and 1 STEP to append, repeated for each pair of (o, i), so 2*n*n STEPS
return multiple // 1 STEP
Adding the above: 1 + n + n2 + 2n2 + 1 = 3n2 + n + 2
This is the code I need to analyse:
i = 1
while i < n
do
j = 0;
while j <= i
do
j = j + 1
i = 2i
So, the first loop should run log(2,n) and the innermost loop should run log(2,n) * (i + 1), but I'm pretty sure that's wrong.
How do I use a theta notation to prove it?
An intuitive way to think about this is to see how much work your inner loop is doing for a fixed value of outer loop variable i. It's clearly as much as i itself. Thus, if the value of i is 256, then then you will do j = j + 1 that many times.
Thus, total work done is the sum of the values that i takes in the outer loop's execution. That variable is increasing much rapidly to catch up with n. Its values, as given by i = 2i (it should be i = 2*i), are going to be like: 2, 4, 8, 16, ..., because we start with 2 iterations of the inner loop when i = 1. This is a geometric series: a, ar, ar^2 ... with a = 1 and r = 2. The last term, as you figured out will be n and there will be log2 n terms in the series. And that is simple summation of a geometric series.
It doesn't make much sense to have a worst case or a best case for this algorithm because there are no different permutations of the input which is just a number n in this case. Best case or worst case are relevant when a particular input (e.g. a particular sequence of numbers) affects the running time of the algorithm.
The running time then is the sum of geometric series (a.(r^num_terms - 1)/(r-1)):
T(n) = 2 + 4 + ... 2^(log2 n)
= 2 . (2^log2 n - 1)
= 2 . (n - 1)
⩽ 3n = O(n)
Thus, you can't be doing work that is more than some constant multiple of n. Hence, the running time of this algorithm is O(n).
You can't be doing some work that is less than some (other) constant multiple of n, since you have to go through the increment in inner loop as shown above. Thus, the running time of this algorithm is also ≥ c.n i.e. it is Ω(n).
Together, this means that running time of this algorithm is Θ(n).
You can't use i in your final expression; only n.
You can easily see that the inner loop executes i times each time it is reached. And it sounds like you've figured out the different values that i can have. So add up those values, and you have the total amount of work.