3

Can anyone guide me to find the time complexity? Does the time complexity change over operating systems?

int fn(int n){
   if(n==1){
     return 1;
    }
    else{
     return(fn(n-1)+ fn(n-1));
    } 
}
Manu
  • 711
  • 8
  • 27
  • 1
    (1) too complex (exponential). (2) no, time complexity is a theoretical estimation, its independent of the environment executing the code. – Jonas Wilms Sep 06 '19 at 05:21
  • hi @JonasWilms , when n=1, the time complexity is 1 but in other cases what will be the time complexity and how can I generalize and write in terms of BigO notation. – Manu Sep 06 '19 at 05:25
  • Wait, this is actually Java right? – Jonas Wilms Sep 06 '19 at 05:32
  • @JonasWilms yes, tag edited – Manu Sep 06 '19 at 05:34
  • 1
    While the answers are correct, I'd like to point out a more intuitive approach: Observe that the cost of __fn(n)__ is twice the cost of __fn(n - 1)__, which is twice the cost of __fn(n - 2)__ and so on... . With every step, we double the cost, so __cost( fn(n) ) = 2 * 2 * 2 ... * cost( fn(1) )__. Convince yourself that this is __2 ^ n__ i.e. exponential. – pius Sep 09 '19 at 04:23

3 Answers3

4

You can make a recurrence relation T which represents the time it would take to compute and input of size N and then use the method of telescoping to help find the Big-O like so:

T(N) = T(N-1) + T(N-1) + c = 2*T(N-1) + c

Here, we can see that the time it will take to compute T(N) will be 2*T(N-1) plus a constant amount of time c. We can also see by your function that:

T(1) = b

Here, we can see by your base case that there are no recursive calls when N=1, so, it will take a constant time b to compute T(1).

If we take a look at T(N), we need to find out what T(N-1) is, so computing that we get:

T(N-1) = 2*T(N-2) + c

Computing T(N-2) we get:

T(N-2) = 2*T(N-3) + c

Thus, we can sub these back into each other...

T(N-1) = 2*(2*T(N-3) + c) + c = 4*T(N-3) + 3c

T(N) = 2*(4*T(N-3) + 3c) + c = 8*T(N-3) + 7c

By looking at the pattern produced by stepping down into our equation, we can generalize it in terms of k:

T(N) = 2^k * T(N-k) + ((2^k)-1 * c)

We know that our recursive calls will stop when T(N-k) = T(1), so we want to find when N-k = 1, which is when k = N-1, so subbing in our value of k and removing the constant-variable times, we can find our Big-O:

T(N) = (2^N) * T(1) + (2^N)-1 * c
= (2^N) * b + (2^N)-1*c
= O(2^N)     (-1, b & c are constants, so they can be removed, giving 2*(2^N), where 2* is a constant, giving 2^N)

Time complexity is a measurement of how well an algorithm will scale in terms of input size, not necessarily a measure of how fast it will run. Thus, time-complexity is not dependent on your operating system.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
3

The function is a recursive function (it calls itself). In that case, its time complexity is either linear or exponential (or something else, which we won't cover here):

It is linear, if you can do TCO (tail call optimization), or in other words, turn the function into a loop:

  int loop(int i, int count) {
    if(i > 10) return count;
    return loop(i - 1, count + 1);
 }

 loop(0, 0);

 // can be turned into
 int count = 0;
 for(int i = 0; i <= 10; i++) {
   count = count + 1;
 }

Otherwise, it is exponential, as every call will execute the function again m times, and each of those m calls, calls the function again m time and so on. This will happen until the depth n is reached, so the time complexity is:

 O(m ^ n)

Now m is kind of a constant, as the number of recursive calls doesn't change (it's two in your case), however n can be changed. Therefore the function has exponential time complexity. That's generally bad, as exponential numbers get really large for relatively small datasets. In your case however, it is trivial to optimize. a + a is the same as a * 2, thus your code can be turned into:

int fn(int n){
   if(n==1){
        return 1;
    }  else {
       return fn(n - 1) * 2;
    } 
 }

And that is .... linear!

Does the time complexity change over operating systems?

No, the time complexity is an abstract concept, it doesn't depend on the computer, operating system, language,... You can even run it on an automaton.

when n=1, the time complexity is 1...

No! n is not a constant. n is part of the input, and time complexity is a way to estimate the time depending on the input.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • what's your view on Aditya's Approach? – Manu Sep 06 '19 at 05:39
  • 1
    If you look close, he basically comes to the same conclusion. – Jonas Wilms Sep 06 '19 at 05:53
  • 1
    "The function is a recursive function (it calls itself). In that case, its time complexity is either linear or exponential." This seems entirely overgeneralised and untrue. Many functions can be defined recursively with a variety of time complexities. – moreON Sep 08 '19 at 22:43
  • @moreON indeed, I mentioned "linear or exponential" cause they were relevant for the following argument, I tried to clarify that sentence. – Jonas Wilms Sep 09 '19 at 05:06
2

Here is the approach I would take.

from the function definition we can deduce that

O(f(n)) = c + 2 * O(f(n-1))

If we ignore constant terms

O(f(n)) = 2 * (2 * f(n-2))

so we can say the complexity here is O(2^n)

Aditya
  • 771
  • 5
  • 11