题目:
定义超级和函数F如下:
F(0, n) = n,对于所有的正整数n..
F(k, n) = F(k – 1, 1) + F(k – 1, 2) + … + F(k – 1, n),对于所有的正整数k和n.
请实现下面Solution类中计算F(k, n)的函数(1 <= k, n <= 14).
class Solution {
public:
int F(int k, int n) {
}
};
例1:F(1, 3) = 6
例2:F(2, 3) = 10
例3:F(10, 10) = 167960
解题思路:
这题有一点动态规划的意思,但是已经把递归公式给出来了,所以要做的就是把递归的算法再进行修改,减少重复计算的次数。因此可以用一个二维数组来记录已经计算过的值。如果已经计算过就直接使用不再重复计算。代码如下:
int f[15][15];
class Solution {
public:
int F(int k, int n) {
if(k == 0){
f[k][n] = n;
return n;
}
for(int i = 1; i <= n; i++){
if(f[k-1][i] > 0)
f[k][n] += f[k-1][i];
else
f[k][n] += F(k-1, i);
}
return f[k][n];
}
};
但是这样的算法其实还是十分低效的,仍然有许多重复计算。在把递归树画出来之后我发现,树的每一层的k值是逐层递减的,每个节点的子节点数也和n值一样。因此可以使用一个三层的循环,一层一层计算出f[n][k]的值。代码如下:
int f[15][15];
class Solution {
public:
int F(int k, int n) {
for(int i = 1; i <= n; i++)
f[0][i] = i;
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
for(int a = 1; a <= j; a++){
f[i][j] += f[i-1][a];
}
}
}
return f[k][n];
}
};