Time complexity of a funcion with function*function in a loop - time-complexity

can you help me please to find the complexity of the following function:
proc (int n)
{
for (i=0 ; i<n ; i++)
{
x = g(n)+f(n) ;
for (j=0 ; j<n ; j++)
{
y=h(j)*g(j) ;
}
}
return x+y ;
}
With f = O(n^2), g = O(n), h = Θ(log(n)).
The things I am not sure:
What is the complexity of "y = h(j) * g(j)", as to me n*log(n)?
Is there a difference in complexity if in the loop is "y = h(j) * g(j)" or just "h(j) * g(j)"?
Is it right, that the complexity of "x = g(n) + f(n)" is n + n^2?
Thank you!

Complexity of inner loop (sum of h*g)
Since h(j) = Θ(log(j)) and g(j) = O(j), the complexity of h(j).g(j) is O(j.log(j)), that is <= K.j.log(j) for K > 0. Therefore the inner loop yields
K.(1.log(1) + 2.log(2) + ... + (n-1).log(n-1))
<= K'.n^2.log(n)
For a well-chosen constant K' and the inner loop gives a complexity O(n^2.log(n)).
Complexity of g + f
g = O(n) and f = O(n^2) so the complexity of f + g is O(n^2).
Overall complexity
A: Sum of n terms O(n^2) for f+g gives O(n^3).
B: Sum of terms j^2log(j) for 0 <= j < n gives O(n^3.log(n)).
Therefore the complexity of your method is O(n^3.log(n)).

Big O of x = O(n^2)
Big O of y = O(n log(n))
Now to compute the Big O of whole algorithm, we have to look at the inner most loop. And in this case, the inner most loop is contained in y = h(j) * g(j).
The Big O can be computed starting from the lowest and going towards up.
The Big O of x would be added not multiplied, because it is on the same level as of the inner for loop.
Big O = O(n log(n)) * O(n) * O(n) + O(n^2)
It can be written as:
Big O = O ((n log(n) * n * n) + (n * n^2))
Big O = O((n^3 log(n) + n^3)
Neglecting smaller terms would give us:
Big O = O(n^3 log(n))

Related

How to find time and space complexity for this algorithm?

I need to find time and space complexity for this java code for recursive calculation of the determinant of a matrix:
public int determinant(int[][] m) {
int n = m.length;
if(n == 1) {
return m[0][0];
} else {
int det = 0;
for(int j = 0; j < n; j++) {
det += Math.pow(-1, j) * m[0][j] * determinant(minor(m, 0, j));
}
return det;
}
}
public int[][] minor(final int[][] m, final int i, final int j) {
int n = m.length;
int[][] minor = new int[n - 1][n - 1];
int r = 0, s = 0;
for(int k = 0; k < n; k++) {
int[] row = m[k];
if(k != i) {
for(int l = 0; l < row.length; l++) {
if(l != j) {
minor[r][s++] = row[l];
}
}
r++;
s = 0;
}
}
return minor;
}
Help: Determine the number of operations and memory consumption of the algorithm with respect to n, and after dividing by n^2 you will get the desired result.
I'm confused. I calculate the time complexity as the sum of the input size (n^2) and the number of steps, and the space complexity as the input size. (?) So its O(n^2) but I don't think I'm doing it right. And why should I divide it (help is from the teacher).
Can someone explain to me how to calculate this in this case?
Let us see. For an input matrix of size n, denote the time complexity as T(n).
So, for a matrix of size n:
if n = 1, we have the answer right away: T(1) = O(1);
otherwise, we loop over j for a total of n times, and for each j, we:
construct a minor in O(n^2) (the minor function), and then
run the function recursively for that minor: this one takes T(n-1) time.
Putting it all together, we have T(1) = O(1) and T(n) = n * (n^2 + T(n-1)).
To understand what is going on, write down what is T(n-1) there:
T(n) = n * (n^2 + T(n-1)) =
= n * (n^2 + (n-1) * ((n-1)^2 + T(n-2)))
And then, do the same for T(n-2):
T(n) = n * (n^2 + T(n-1)) =
= n * (n^2 + (n-1) * ((n-1)^2 + T(n-2))) =
= n * (n^2 + (n-1) * ((n-1)^2 + (n-2) * ((n-2)^2 + T(n-3)))) = ...
Then we write what is T(n-3), and so on.
Now, open the brackets:
T(n) = n * (n^2 + (n-1) * ((n-1)^2 + (n-2) * ((n-2)^2 + T(n-3)))) =
= n^3 + n * (n-1) * ((n-1)^2 + (n-2) * ((n-2)^2 + T(n-3)))) =
= n^3 + n * (n-1)^3 + n * (n-1) * (n-2) * ((n-2)^2 + T(n-3)))) =
= n^3 + n * (n-1)^3 + n * (n-1) * (n-2)^3 + n * (n-1) * (n-2) * T(n-3)))) =...
As we can see going further, the highest term among these, in terms of n, will be
T(n) = n * (n-1) * (n-2) * ... * 3 * 2 * 1^3, which is just n! (n-factorial).
The above is about time complexity.
To address space complexity, consider how recursion uses memory.
Note that it is much different from what happens to the time.
The reason is that, at each point of time, we are in some single particular branch of the recursion tree, and at this time other branches don't use the memory they need.
Therefore, unlike with time, we can't just add up the total memory used by all recursive calls.
Instead, we have to consider all branches of the recursion tree, and find the one that uses maximum memory.
In this particular case, it is just any deepest branch of the recursion.
Denote the memory consumption by M(n) where n is the matrix size.
if n = 1, we have the answer right away: M(1) = O(1);
otherwise, we loop over j for a total of n times, and for each j, we:
construct a minor that takes O(n^2) memory (the minor function), and then
run the function recursively for that minor: this one takes M(n-1) memory.
Note that the loop does not accumulate memory used by minors.
Instead, when we construct the minor for next j, the minor for previous j is not needed anymore.
Thus we have M(n) = n^2 + M(n-1).
Again, writing down what is M(n-1), then M(n-2), and so on gets us to
M(n) = n^2 + (n-1)^2 + (n-2)^2 + ... + 3^2 + 2^2 + 1^2, which is O(n^3) with some constant factor we need not care about.
So, by the above reasoning, the answer is: T(n) = O(n!) and M(n) = O(n^3).
What's the hint about, with dividing by n^2, I don't have a clue, sorry!

Time complexity of below pseudocode

void buzz(int num, int [] a)
{
for(int i=1;i<num;i*=2){
for(int j=0;j<a[i]%num;j++){
print(num);
}
}
}
I understand that the outer for loop runs for log n times. Need help in understanding the complexity of the inner loop and the overall.
Let us assume num = 2^n for simplicity.
The inner loop runs a[i] % num times, which is comprised in range [0, num-1]. The outer loop runs n times so you can conclude O(num.log(num)) = O(n.2^n) worst-case complexity.
For a precise evaluation, let r[i] := a[i] % num. Then the number of print's is
r[1] + r[2] + r[4] + r[8] + ... r[2^(n-1)].
This is n times the average r (for the relevant indexes; the expectation of r could be (num-1)/2)).

TIme complexity for a specific loop

What is the time complexity and tilde for the loop below?
for (int i = N/2; i < N; i++) {
for (int j = i; j < N; j++) {
doSomething(i, j);
}
}
I think that it runs N/2 + (N/2 + 1) + (N/2 + 2) + ... + (N-1) times, but how do I get it's time complexity and tilde?
For example - if N = 100, the loop will run 50 + 51 + 52 + 53 + ... + 99 times.
I am assuming doSomething(i, j); is not iterating all the elements between i and j; if this is the case, the complexity of this algorithm is O(N^2).
The outer loop for (int i = N/2; i < N; i++) { will execute O(N) times, cause N/2 is actually constant value.
The inner loop in worst case will execute N times (or N - i times) too, this will also merge with previous O(N).
Therefore, overall time complexity will be O(N^2) in worst case scenario.
The inner loop is executed:
N/2-1 times for i = N/2,
N/2-2 times for i = N/2+1
....
1 time for i = N-2
therefore the total time for the inner loop is :
(N/2-1) + (N/2-2) + .... (N/2-k) where k = N/2 - 1
= N/2*k - (1 + 2 + ... + k)
= N/2*(N/2-1) - (N/2-1)(N/2)/2
= N/2(N/2 - 1 - N/4 + 1/2)
= N/2(N/4 - 1/2)
= N^2/8 - N/4
Hence the order of growth of the code is of N^2
If you consider tilde notation which is defined as :
"∼g(n) to represent any quantity that, when divided by f(n), approaches 1 as n grows" from here, you can see that ~g(n) = ~N^2/8 because as N grows (N^2/8)/(N^2/8-N/4) approaches 1.

What is the asymptotic running time of this pseudocode?

In the following piece of code, f() is any function taking time of Θ(1). The time complexity should be Θ(n4/3), can someone explain why?
for(int i = 1; i ≤ n; i = 2∗i) {
for(int j = 1; j∗j∗j ≤ n; j = j+1) {
for(int k = 1; k ≤ i∗i; k = k + i) {
f();
}
}
}
By my analysis, the first for loop takes Θ(log2 n) time, the second for loop is Θ(n1/3), and the third for loop is Θ(i). So in total we have Θ((log2 n) × n1/3 × i).
Since i can be n, we have Θ((log2 n) × n1/3 × n) = Θ(n4/3 log2 n). Where is my mistake?
Your bound is not tight, because you counted i as Θ(n), but i is not Θ(n) on average. Consider the sequence of values that i takes, and add these up to count the total number of iterations for the inner loop. We can ignore the middle loop over j for now, since it is independent of i and k.
The sequence of values for i is 1, 2, 4, 8, ... up to n. If we say n = 2r for some r, this is a geometric progression with sum 2r+1 - 1, which is about twice as big as n, so it's Θ(n). This counts both the outer and inner loop; the middle loop gives another factor of Θ(n1/3), and hence the overall complexity is Θ(n4/3) as required.

What is the time complexity of this nested loop?

I stumbled upon a loop for which I am not sure what the time complexity is. It is the following loop:
for(i = 1; i <= n^2; i++){
for(j = 1; j <= i; j++) {
//some elementary operation
}
}
I would have argued that the outer for-loop runs in n^2 and the inner for loop would also run in n^2 as for every iteration of the outer-loop we do n^2 - (n^2 - 1), n^2 - (n^2 - 2),..., n^2. Am I totally going in the wrong direction here?
So the time complexity would be in n^4
The number of operation will be :
1 + 2 + 3 + 4 + 5 + ... + n²
Which is equal to (n² * (n² - 1)) / 2.
The Big O notation is O(n^4). You are correct.
It's a simple arithmetic progression happening here.
Every new iteration is bigger by 1.
Outer loop will do n^2 operations which will result for following sequence:
1 + 2 + 3 + ... + n + ... + n^2 = n^2 (n^2+1) / 2 = O(n^4)