【发布时间】:2017-04-05 13:35:02
【问题描述】:
我在 Java 中创建了以下简单算法,以递归方式计算帕斯卡三角形,形式为 2D 整数列表:
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);
}
}
我需要知道这个算法的时间复杂度。我在 StackOverflow 上找到了another question,它给出了 getValueAtPoint 函数的时间复杂度为 O(2^n/sqrt(n))。我想,由于这个函数嵌入在两个嵌套的for循环中,整个帕斯卡三角形的时间复杂度是O(sqrt(n^3)*2^n)。我很确定这个推理是正确的。
另一方面,我设计了一种完全不同的方式来思考这个问题,如下所示:
帕斯卡三角形有一个特定的性质,称为帕斯卡推论 8。这个性质表明给定行 r 上所有系数的总和等于 2^r,r 从 0 开始。
您还可以注意到,我的代码示例中的 getValueAtPoint 函数将继续递归调用自身,直到它在某个时刻返回 1。这意味着帕斯卡三角形中的所有系数都是通过将该系数的值加 1 来形成的。
由于加 1 需要一个常数时间,因此可以说计算三角形中给定行所需的时间等于某个常数时间乘以该行中所有系数的组合值。这意味着三角形中给定行 r 的时间复杂度必须为 2^r。
计算整个三角形所需的时间等于计算三角形中所有行所需时间的总和。这会产生一个几何级数,它计算所有 2^r 的总和,因为 r 从 0 到 n-1。
利用几何级数的求和属性,这个级数可以改写成下面的form。
这意味着根据这个最后推导的算法的时间复杂度是O(2^n)。
这两种方法会产生不同的结果,尽管它们在我看来都是合乎逻辑且正确的。我的问题首先是这两种方法是否正确,并且是否可以同时被视为正确?我认为它们都是正确的,但第二个更准确,因为对于第一个,getValueAtPoint 函数采用最坏的情况,并应用于所有系数,这显然是实际情况并非如此。这是否意味着第一个变得不正确,即使它背后的逻辑是正确的,只是因为存在更好的方法?
【问题讨论】:
标签: java recursion time-complexity pascals-triangle