finding the time and space complexity of the following code - algorithm

what is the space and time complexity of following code and how
large(n) //n is +ve
{
if(n<=1)
return n;
sum=0;
for(i=1 to n-1)
sum=sum+large(i);
return sum;
}

You have: T(n <= 1) = O(1) and T(n) = T(n-1) + ... + T(1) + O(1).
Solving this recurrence, you get T(n) = O(n!).
Besides, you can observe that large(k) is calculated O(n) times. Actually you can inscreasingly speed up the whole computation by noticing that this algorithm is a perfect candidate for dynamic programming!

Related

How to calculate time complexity of this recursion?

I'm interested in calculating the following code's time and space complexity but seem to be struggling a lot. I know that the deepest the recursion could reach is n so the space should be O(n). I have no idea however how to calculate the time complexity... I don't know how to write the formula when it comes to recursions similar to this forms like: f(f(n-1)) .
if it was something like, return f3(n-1) + f3(n-1) then i know it should be O(2^n) since T(n) = 2T(n-1) correct?
Here's the code:
int f3(int n)
{
if(n <= 2)
return 1;
f3(1 + f3(n-2));
return n - 1;
}
Thank you for your help!
Notice that f3(n) = n - 1 for all n, so the line f3(1 + f3(n-2)), first f3(n-2) is computed, which returns n - 3 and then f3(1 + n - 3) = f3(n-2) is computed again!
So, f3(n) computes f3(n-2) twice, alongside with some O(1) overhead.
We got the recursion formula T(n) = 2T(n-2) + c for some constant c, and T(n) is the running time of f3(n).
Solving the recursion, we get T(n) = O(2^(n/2)).

Selection Sort Recurrence Relation

up front this is a homework question but I am having a difficult time understanding recurrence relations. I've scoured the internet for examples and they are very vague to me. I understand that recurrence relations for recursive algorithms don't have a set way of handling each one but I am lost at how to understand these. Here's the algorithm I have to work with:
void selectionSort(int array[]) {
sort(array, 0);
}
void sort(int[] array, int i) {
if (i < array.length - 1)
{
int j = smallest(array, i); T(n)
int temp = array[i];
array[i] = array[j];
array[j] = temp;
sort(array, i + 1); T(n)
}
}
int smallest(int[] array, int j) T(n - k)
{
if (j == array.length - 1)
return array.length - 1;
int k = smallest(array, j + 1);
return array[j] < array[k] ? j : k;
}
So from what I understand this is what I'm coming up with: T(n) = T(n – 1) +cn + c
The T(n-1) represents the recursive function of sort and the added cn represents the recursive function of smallest which should decrease as n decreases since it's called only the amount of times that are remaining in the array each time. The constant multiplied by n is the amount of time to run the additional code in smallest and the additional constant is the amount of time to run the additional code in sort. Is this right? Am I completely off? Am I not explaining it correctly? Also the next step is to create a recursion tree out of this but I don't see this equation as the form T(n) = aT(n/b) + c which is the form needed for the tree if I understand this right. Also I don't see how my recurrence relation would get to n^2 if it is correct. This is my first post too so I apologize if I did something incorrect here. Thanks for the help!
The easiest way to compute the time complexity is to model the time complexity of each function with a separate recurrence relation.
We can model the time complexity of the function smallest with the recurrence relation S(n) = S(n-1)+O(1), S(1)=O(1). This obviously solves to S(n)=O(n).
We can model the time complexity of the sort function with T(n) = T(n-1) + S(n) + O(1), T(1)=O(1). The S(n) term comes in because we call smallest within the function sort. Because we know that S(n)=O(n) we can write T(n) = T(n-1) + O(n), and writing out the recurrence we get T(n)=O(n)+O(n-1)+...+O(1)=O(n^2).
So the total running time is O(n^2), as expected.
In selection sort algo
Our outer loop runs for n- 1 times (n is the length of the array) so n-1 passes would be made... and then element is compared with other elements ....so n-1 comparisons
T(n)=T(n-1) + n-1
Which can be proved as O(n^2) by solving the particular relation ..

How to get Time Complexity(Big-O) on this recursive function?

How to get Time Complexity this function?
fun(int n){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
print(" ");
}
}
fun(n-3)
}
Suppose the run time of f(n) is T(n). You have to loops in each function call. so The compelxity of the loops are O(n^2).
the f(n) has 2 loops ( O(n^2) ) and one f(n-3). so we come up to the equation below:
T(n) = T(n-3) + O(n^2)
which also can be written as:
T(n) = T(n-3) + (n^2)*(1^n)
So the equal equation to a above is: (r^3 - 1 )[(r-1)^3]=0
so we have r=1 ( 6th degree) so the T(n) will be like this:
T(n) = [a1 + a2*n + a3*n^2 + a4*n^3 + a5*n^4 + a6*n^5 ]*(1^n)
So at last it is obvious that for a1,a2,a3,a4,a4,a5,a6!=0 (which only can be found by initial value of f(n), the result is
T(n) = O(n^5)
There is no bottom to the recursion, so it will run infinitely long. Since the growth rate of the function is independent of the input (n), it is an O(1) function (no matter how big n is, the execution time is always the same, which is to say, infinite).
If there were a bottom to the recursion, we can see how fast the function grows for higher values of n. Each n adds another pass through the inner loop, multiplied by another pass through the outer loop, multiplied by the recursion depth, so that is n*n*n = O(n^3).
It is true that the recursion grows a little bit more slowly than the two loops, but in the end it does grow linearly with n, which means it counts as O(n) in its own right.

Recursion, inner loop and time complexity

Consider the following function:
int testFunc(int n){
if(n < 3) return 0;
int num = 7;
for(int j = 1; j <= n; j *= 2) num++;
for(int k = n; k > 1; k--) num++;
return testFunc(n/3) + num;
}
I get that the first loop is O(logn) while the second loop gives O(n) which gives a time complexity of O(n) in total. But due to the recursive calls I thought the time complexity would be O(nlogn), but apperantly it is only O(n). Can anyone explain why?
The recursive call pretty much gives the following for the complexity(denoting the complexity for input n by T(n)):
T(n) = log(n) + n + T(n/3)
First observation as you correctly noted is that you can ignore the logarithm as it is dominated by n. Now we are only left with T(n) = n + T(n/3). Try writing this up to 0 for instance. We have:
T(n) = n + n/3 + n/9+....
You can easily prove that the above sum is always less than 2*n. In fact better limits can be proven but this one is enough to state that overall complexity is O(n).
For procedures using a recursive algorithm such as the following:
procedure T( n : size of problem ) defined as:
if n < base_case then exit
Do work of amount f(n) // In this case, the O(n) for loop
T(n/b)
T(n/b)
... a times... // In this case, b = 3, and a = 1
T(n/b)
end procedure
Applying the Master theorem to find the time complexity, the f(n) in this case is O(n) (due to the second for loop, like you said). This makes c = 1.
Now, logba = log31 = 0, making this the 3rd case of the theorem, according to which the time complexity T(n) = Θ(f(n)) = Θ(n).

Solving Recursion in fibonacci numbers

I'm unaware of the mathematics in this algorithm and could use some help.
Algorithm:
if n<2 then
return n
else return fibonacci(n-1) + fibonacci(n-2)
Statement
n < 2 is O(1)
Time n >=2 is O(1)
Return n is O(1)
Time n>=2 is -
Return fib(n-1) + fib(n-2) is -
and time n>=2 is T(n-1) + T(n-2) +O(1)
Total: O(1) T(n-1) + T(n-2) + O(1)
T(n) = O(1) if n < 2
T(n) = T(n-1) + T(n-2) + O(1) if n>=2
I think you're supposed to notice that the recurrence relation for this function is awfully familiar. You can learn exactly how fast this awfully familiar recurrence grows by looking it up by name.
However, if you fail to make the intuitive leap, you can try to bound the runtime using a simplified problem. Essentially, you modify the algorithm in ways guaranteed to increase the runtime while making it simpler. Then you figure out the runtime of the new algorithm, which gives you an upper bound.
For example, this algorithm must take longer and is simpler to analyze:
F(n): if n<2 then return n else return F(n-1) + F(n-1)
By induction: if calculation of fib(k) takes less than C*2^k for all k < n, for the calculation tome of fib(n) we've got
T(n) = T(n-1) + T(n-2) + K < C*2^(n-1) + С*2^(n-2) + K
= 0.75*C*2^n + K < C*2^n
for sufficiently big C (for C > K/0.25, as 2^n > 1). This proves that T(n) < C*2^n, i.e. T(n) = O(2^n).
(Here T(n) is the time for calculation of fib(n), K is the constant time needed for calculating fib(n) when both fib(n-1) and fib(b-1) are [already] calculated.)
You need to solve the recurrence equation:
T(0) = 1
T(1) = 1
T(n) = T(n-1) + T(n-2), for all n > 1

Resources