0

I have created the following simple algorithm in Java that computes the Pascal triangle in a recursive way, in the form of a 2D list of ints:

public class PascalTriangleRec{
    private final int[][] points;

    public PascalTriangleRec(int size){
        points = new int[size][];
        for (int i =0;i<size;i++){
            int[] row  = new int[i+1];
            for (int j = 0;j<=i;j++){
                row[j]=getValueAtPoint(i,j);
            }
            points[i]=row;
        } 
    }
    public static int getValueAtPoint(int row, int col){
        if (col == 0 || col == row) return 1;
        else return getValueAtPoint(row-1,col-1) + getValueAtPoint(row-1,col);
    }
}

I need to know the time complexity of this algorithm. I found another question on StackOverflow that gives the time complexity of the getValueAtPoint function as O(2^n/sqrt(n)). I figured that since this function is embedded in two nested for loops, the time complexity of the entire Pascal triangle is O(sqrt(n^3)*2^n). I am pretty sure this reasoning is correct.

On the other hand I devised a completely different way to think about this problem, which goes as follows:

There is a certain property of Pascal triangles called Pascal's Corollary 8. This property states that the sum of all the coëfficients on a given row r is equal to 2^r, with r starting at 0.

One can also note that the getValueAtPoint function from my code sample will keep recursively calling itself until it returns 1 at some point. This means that all the coëfficients in the Pascal triangle are formed by adding 1 as many times as the value of that coëfficient.

Since adding 1s takes a constant time, one can say that the time needed to compute a given row in the triangle is equal to some constant time multiplied by the combined value of all the coëfficients in that row. This means that the time complexity of a given row r in the triangle must be 2^r.

The time needed to compute the entire triangle is equal to the sum of the time needed to calculate all the rows in the triangle. This results in a geometric series, which computes the sum of all 2^r for r going from 0 to n-1.

Using the summation property of the geometric series, this series can be rewritten in the following form.

This means that the time complexity of the algorithm according to this last derivation is O(2^n).

These two approaches yield different results, even though they both seem logical and correct to me. My question is in the first place if both these approaches are correct, and if both can be seen as correct at the same time? As I view it both of them are correct, but the second one is more accurate since for the first one the worst-case scenario is taken for the getValueAtPoint function, and applied to all coëfficients, which is clearly not the case in reality. Does this mean that the first one becomes incorrect, even though the logic behind it is correct, just because a better approach exists?

Community
  • 1
  • 1
user3423641
  • 15
  • 1
  • 5

1 Answers1

1

The simple answer is "too many variables". First of all, your analysis is exactly correct: the complexity depends on the sum of all the values computed. The same logic underlies the answer that got you O(2^n/sqrt(n)).

There are two problems:

  • Little problem: Stirling's approximation is just that: some terms are elided. I think they fall out when you combine all the loops, but I'd have to work through the nasty details to be sure.
  • Big problem: the values of n you combine are not the same n. That last n value you incorporated is i running from 0 to size; each value of i becomes n for an initial call to getValueAtPoint.

Try doing the sum from 0 to n on your previous complexity, and see what you get?

.

Prune
  • 72,213
  • 14
  • 48
  • 72
  • I think if I understand correctly that you mean the second approach does not take into account all the recursive calls to getValueAtPoint, since for i=n there are a lot of calls that are made that do not directly return 1 but that still need to be taken into account? Do you mean I should think of the nested for loops like a sum for the first derivation? The problem is that because of the Sqrt(n) in the first solution, I couldn't find a way to simplify the resulting series mathematically. So if I am not mistaken the first approach is the only totally correct one? – user3423641 Apr 05 '17 at 22:27
  • Yes, that was my intent. However, my "little problem" point is a major one in application, now that I look at it again: Stirling's work derives the use of sqrt(n) as part of the approximation; that's *not* a direct form. To do that summation, you'd have to dive back into his error terms as well. Including those *should* reverse the ugliness of that sqrt. Personally, I'd write a small program to compute that approximation, do the summation, and see how close it comes to your 2^n figure. – Prune Apr 05 '17 at 22:30
  • You would have to excuse me but I do not have a very theoretical background. I do not know much of the Stirling approximation, and just assumed that the derivation on the other post I referred to to get to the O(2^n/Sqrt(n)) was correct. On the other hand I can provide you with testdata I gathered. I plotted the results using both approximation formula's. The results can be found here: http://imgur.com/a/HhXCV. As you can see the 2^n approach seems to work best. Does this mean that my second approach is better after all and the extra recursive calls I forgot about are negligible? – user3423641 Apr 05 '17 at 22:57
  • 1
    Right: the extra calls are of a lower order of complexity; I think it's O(n), which drops out of the complexity computation. Don't worry about not being able to transform the summation of Stirling's work; *I* can't do it any more, myself. My point is that if you *could* work through it, I expect that you'd find that all those detailed terms combine to arrive at that same 2^n result. – Prune Apr 05 '17 at 23:03
  • Thank you very much for your time! I think I understand this enough now to continue with my project. Your help has been very useful for me. – user3423641 Apr 05 '17 at 23:22