what is space complexity for this program? - c

This is just a test function for calculating space complexity if we consider the
number of stack frames than it will be o(n) but what about those arrays a and b inside for loop and 2-d which will also take some memory in every recursive call,my professor told us that space complexity is size of stack frame but it also consuming some space in that for loop also
Should i consider both that is stack frame and two arrays and 2-d array or give any one of them priority and why?
I am just focusing on space complexity so forget about the result or garbage collection
testfun(n){
if(n==0)
return;
int c[10][10];
int *a=malloc(sizeof(int)*n);
int *b=malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
{ a[i]=n+2*i;
b[i]=n+3*i;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
c[i][j]=1;
}
testfun(n-1);
free(a);
free(b);
}

It might be you think about the free function. But, recursion is happened before theese free function. Hence, in each call of the function, depends on the value of the input (i), size of the allocated space is 2i. As the stopping time is on n == 0, the total space complexity is sum_{i = 1}^{n} 2*i = 2*n(n+1)/2 = \Theta(n^2).

The space complexity of the question is O(n)if you have freed the memory locations before call to the function, since each call to the function needs to remember the stack variables.
free(a);
free(b);
test(n - 1);
Else in each function call the function allocates O(n) space and same in subsequent recursive calls as well. So space complexity is O(n^2).
Using Substitution method:
S(0) = 0
S(n) = S(n - 1) + 2n -------- (1)
S(n - 1) = S(n - 2) + 2 (n - 1) -------- (2)
S(n - 2) = S(n - 3) + 2 (n - 2) -------- (3)
Using (1), (2), (3)
S(n) = S(n - 1) + 2n
S(n) = S(n - 2) + 2 (n - 1) + 2n
S(n) = S(n - 3) + 2(n - 2) + 2(n - 1) + 2n
.
.
.
.
S(n) = S(n - k) + 2(n - (k - 1)) + ... + 2n
Let k = n
S(n) = S(n - n) + 2(1) + 2(2) + ... 2(n)
S(n) = S(0) + 2(n * (n + 1)) / 2
S(n) = 0 + n^2 + n
Therefore space complexity is O(n^2).

The space complexity of above program is O(n^2)+O(n) O(n^2) for 2-d matrix and O(n)
for 1-d array

The space complexity of above program is O(n^2).
The reason for this is the a and b are of size n and hence both of them have a space complexity of O(2n) which is nothing but O(n).
Now the recursion is simply from n to 1 and each recursion call consumes O(n) space. Therefore space complexity will be O(n^2).

Related

find time and space complexity

I need to find the time and space complexity of f3.
I think that g has space complexity of log(n), so for the time complexity, but I am not really sure how I find the time and space complexity of f3 because the calling for g is inside the for commend, does it mean the g is being called every time to check if g(i) < n?
int g(int n)
{
if (n <= 1)
return 1;
return g(n / 2) + 1;
}
int f3(int n)
{
int counter = 0;
for (int i = 0; g(i) < n; ++i)
++counter;
return counter;
}
In short:
Time complexity of f3(n) = O(2^n)
Space complexity of f3(n) = O(n)
Space and Time complexity of g(n) = O(log(n))
Note: (here all log that I refer are log base2 link and all notations are in Big O notation)
Details:
The function "g()" returns floor(log(n))+1. The loop in function "f3()" cotinues until the function 'g()' returns n. For g(i) to return 'n', i needs to be '2^(n-1)'.
In order to terminate the loop in "f3()", 'i' needs to reach 2^(n-1). So 'g()' is called 2^(n-1) times.
So Time complexity of "f3()" = 2^(n-1) x (time complexity of g()) = 2^n x (log n) = O(2^n)
Largest memory used will be during the last call of 'g(i)' where i==2^(n-1).
Therefore space complexity of "f3()" = log(2^(n-1)) = O(n)
As g(n) will run in Theta(log(n)) and each time adds 1 to the final result, the final value of g(i) will be \ceil{log(i)} + 1. On the other hand, the loop inside f3 will run while g(i) < n. It means the loop will iterate up to 2^n. Hence, f3 will run 2^n times. Hence, the time complexity of f3(n) = sum_{i=1}^{2^n} log(i) = log((2^n)!) = \Theta(n * 2^n) (as log((2^n)!) ~ (2^n) log(2^n)).
About space complexity, the maximum depth of g(i), will be when i = 2^n, which is n (n recursive calls). Hence, the space complexity of f3 will be \Theta(n).

Space complexity of recursive function (Time & Space)

There is recursion function below, and I did not calculated time & space complexity. I looked at some resources, but it was not clear enough for me the understanding. Could anyone explain the way of solving in the simplest way, and answers the question?
By the way, I tried to solve time complexity, and I found O(2^n). Is it correct?
int func(int n) {
if (n < 3)
return 3;
else {
return func(n-3)*func(n-3);
}
}
Yes, the time complexity is indeed O(2 ^ n).
The recurrence relation for time complexity is:
T(n) = 2 * T(n - 3)
Applying the above equation k times:
T(n) = 2 * 2 * 2 ... k times * T(n - 3 * k) = 2 ^ k * T(n - 3k)
When k is n/3, T(n) = 2 ^ k = 2 ^ (n / 3) = O(2 ^ n)
There's only one function running at a time and stack depth can be k at max.
So, space complexity is n / 3 or O(n)

if else recursion worst time complexity

I have some trouble to figure out the worst time complexity of below code.
(This is not a homework, see https://leetcode.com/problems/integer-replacement/description/.)
int recursion (int n) {
if (n == 1)
return 0;
if (n % 2 == 0) {
return recursion(n/2) + 1
} else {
return min(recursion(n / 2 + 1) + 1, recursion(n - 1)) + 1;
}
}
The only thing I know is when N == 2 ^ k(k > 0), worst time complexity is O(logN).
However, I am unclear when N is not 2^k. Because even number / 2 can still get odd number. Some people said it is still O(LogN), but I am not convinced.
I know the code is not best solution, just wanna analyze the time complexity. I tried recursion tree and aggregate analysis, seems not help.
If n is even, we know that T(n) = T(n/2) + 1, and if n is odd we know that
T(n) = T(n/2 + 1) + T(n-1) + 1. In the latter case, as n is odd we know that n-1 must be even. if n/2 + 1 is even T(n) = T(n/4) + T(n/2) + 3 and if n/2 + 1 is odd T(n) = 2*T(n/4) + T(n/2) + 3.
From the above discussion, in the worst case T(n) is defined based on the T(n/2) and T(n/4) in a general case. From Akra-Bazzi Theorem we can say, T(n) = O(n^((log(1+sqrt(5))-log(2))/log(2))) ~ O(n^0.69) (from the first case) and T(n) = O(n) from the second case (which n/2 + 1 is odd).
However, for the more tight complexity, we should scrutinize more in our analysis.

time complexity of randomized array insertion

So I had to insert N elements in random order into a size-N array, but I am not sure about the time complexity of the program
the program is basically:
for (i = 0 -> n-1){
index = random (0, n); (n is exclusive)
while (array[index] != null)
index = random (0, n);
array[index] = n
}
Here is my assumption: a normal insertion of N numbers is of course strictly N, but how much cost will the collision from random positions cost? For each n, its collision rate increases like 0, 1/n, 2/n .... n-1/n, so expected number of insertions attempts will be 1, 2, 3 .. n-1, this is O(n), so total time complexity will be O(n^2), so is this the average cost? but wow this is really bad, am I right?
So what will happen if I do a linear search instead of keep trying to generate random numbers? Its worst case will obviously be O(n^2>, but I don't know how to analyze its average case, which depends on average input distribution?
First consider the inner loop. When do we expect to have our first success (find an open position) when there are i values already in the array? For this we use the geometric distribution:
Pr(X = k) = (1-p)^{k-1} p
Where p is the probability of success for an attempt.
Here p is the probability that the array index is not already filled.
There are i filled positions so p = (1 - (i/n)) = ((n - i)/n).
From the wiki, the expectation for the geometric distribution is 1/p = 1 / ((n-i)/n) = n/(n-i).
Therefore, we should expect to make (n / (n - i)) attempts in the inner loop when there are i items in the array.
To fill the array, we insert a new value when the array has i=0..n-1 items in it. The amount of attempts we expect to make overall is the sum:
sum_{i=0,n-1} n/(n-i)
= n * sum_{i=0,n-1}(1/(n-i))
= n * sum_{i=0,n-1}(1/(n-i))
= n * (1/n + 1/(n-1) + ... + 1/1)
= n * (1/1 + ... + 1/(n-1) + 1/n)
= n * sum_{i=1,n}(1/i)
Which is n times the nth harmonic number and is approximately ln(n) + gamma, where gamma is a constant. So overall, the number of attempts is approximately n * (ln(n) + gamma), which is O(nlog n). Remember that this is only the expectation and there is no true upper bound since the inner loop is random; it may never find an open spot.
The expected number of insertions attempt at step i is
sum_{t=0}^infinity (1-i/n)^t * (n-i)/n * t
= (n-i)/n * i/n * (1-i/n)^{-2}
= i/(n-i)
Summing over i you get
sum_{i=0}^{n-1} i/(n-1)
>= sum_{i=n/2}^n i / (n-i)
>= n/2 sum_{x=1}^n/2 1/x
>= n/2 * log(n) + O(n)
And
sum_{i=0}^{n-1} i/(n-i)
<= n * sum _{x=1}^n 1/x
<= n * log(n) + O(n)
So you get exactly n*log(n) as an asymptotic complexity. Which is not as bad as you feared.
About doing a linear search, I don't know how you would do it while keeping the array random. If you really want an efficient algorithm to shuffle your array, you should check out Fisher-Yates shuffle.

Space complexity of a given recursive program

Consider the following C-function:
double foo (int n) {
int i;
double sum;
if (n == 0) return 1.0;
else {
sum = 0.0;
for (i = 0; i < n; i++)
sum + = foo (i);
return sum;
}
}
The space complexity of the above function is
1) O(1)
2) O(n)
3) O(n!)
4) O(n^n)
in the above question, according to me, answer should be (2) but answer is given as (3) option. Although it is recursive function but stack will never have more than O(n) stack depth. Can anyone explain me why is this answer (3) and where am I thinking wrong?
If You needed time complexity then it is certainly not O(N!) as many suggest but way less then that it is O(2^N).
Proof:-
T(N) = T(N-1) + T(N-2) + T(N-3) + T(N-4)........T(1)
moreover by above formula
T(N-1) = T(N-2) + T(N-3)...... T(1)
hence T(N) = T(N-1) + T(N-1) = 2*T(N-1)
solving above gives T(N) = O(2^N)
Whereas if you needed space complexity then for recursive function space complexity is calculated by the amount of stack space at max occupied by it at a moment and that in this case cannot exceed of O(N)
But in any case the answer is not O(N!) because that many computations are not done at all so how can stack occupy that much space.
Note:- Try to run the function for n = 20 if it doesnt cause memory overflow then answer given in text will be 20! which is larger than any memory but i think it will run in O(2^20) time without any stack overflow.
Space complexity is O(N). at any given time the space used is limited to:
N*sizeof_function_call_which_is_a_constant.
Think of it like this:
To calculate foo(n) . The program have to calculate: foo(0)+foo(1)+foo(2) ... foo(n-1):
Similarly for foo(n-1). The program have to recursively calculate: foo(0) + foo(1) + ... foo(n-2).
Basically you will have O(foo(n)) = n! + (n-1)! + (n-2)! + ... 1! = O(n!).
Hope this is clear.

Resources