问题描述
这是动态编程算法。
int bin2(int n,int k){
index i,j;
i tn B[0 ][0 k] B[0..n][0..k]; i
for(i=0; i <= n; i++)
for(j=0; j <= minimum(i,k); j++)
if (j 0 || j i) [i][j] 1
i
if (j==0 || j==i) B[i][j] = 1;
else B[i][j] = B[i-1][j-1] + B[i-1][j];
return B[n][k];
}
其空间复杂度为O(n ^ 2)。 可以将其降低为O(n)吗? 如果我可以使用“当行的计算完成时就不需要先前计算的值”的属性,该怎么办? 在上面的代码中,我暗示您可以将k更改为1,将j更改为j%2。我该怎么办?
解决方法
关键是这一行
B[i][j] = B[i-1][j-1] + B[i-1][j];
您会看到,对于当前状态,我们依赖于i-1
和j-1
。我们不需要前面所有的行,只需要第i-1
行。
方法1
您应该希望将其更改为类似
B[j] += B[j - 1];
保持覆盖相同的一维数组,即为每个j
遍历i
。
尝试自己解决。如果您仍然想看看解决方案,那就是我回答的结尾。
方法2
有些人喜欢保留两行,其中第一行较早,而第一行保留至当前。通过使用0
,它们在第1
行和第mod
行之间交替。 (i+1) % 2
会给1
,i = 0
会给0
。但是此方法使用两个数组,而不是方法一所示的数组。
方法3
类似于方法2。有些人保留了先前和当前的两个数组。他们交换整个数组,而不是更改要填充的当前数组。交换发生在i = 1
循环之后和j
循环内部。有关此方法,请参考@Maurycyt的解决方案。
有效的方法:方法1>方法2>方法3
方法1的解决方案:
i
,
我对您的代码感到困惑,该代码似乎有多种错别字,但是您可以使用{n \ choose k} =(n!)来评估线性空间复杂度中的{n \ choose k}。 /(k!*(nk)!)是Pascal三角形的第n行的第k个元素(您似乎已经知道,我只是确保它在这里)。
int nchoosek(int n,int k)
{
int i,j; //These are indices of the row and column respectively
int oldrow [n+1],newrow [n+1]; //n+1 is the largest size of a row we will need.
//we will be computing a row of Pascal's triangle based on the previous row,//then swapping the two.
for (i = 0; i <= n; i++) //we iterate over the rows
{
for (j = 0; j <= i; j++) //we iterate over the elements in a row,there are i+1 elements in row i,thus n+1 elements in row n.
{
if (j == 0 || j == i)
newrow[j] = 1; //we set the first and last element of a row to 1.
else
newrow[j] = oldrow[j-1] + oldrow[j]; //we set the other elements to the sum of the two elements above them in Pascal's triangle.
}
swap(oldrow,newrow); //we swap the two arrays,and will now be counting the next row,using the row which we just counted.
}
//the i-th row of Pascal's triangle will always end up in the oldrow array
return oldrow[k]; //we return its k-th element.
}