我试图从f_rec(递归函数)到f_iter(迭代函数),但我不能。 (我的逻辑是创建一个循环来计算f_rec(n-1)的结果。
int f_rec(int n)
{
if(n>=3)
return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
else
return 1;
}
int f_iter(int n)
{
}
我还认为f_rec的时间复杂度是3 ^ n,如果我错了,请纠正我。
谢谢
答案 0 :(得分:1)
您始终可以计算最后三个中的最新值。只需从头开始计算并始终保存最后三个:
int f_iter (int n) {
int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++
for (int i = 3; i <= n; ++i) {
int new_value = last3[0] + 2 * last3[1] + last3[2];
last3[0] = last3[1];
last3[1] = last3[2];
last3[2] = new_value;
}
return last3[2];
}
此解决方案需要O(1)内存和O(n)运行时。可能存在一个在O(1)中计算这个的公式(很可能是),但我想为了演示迭代技术,这是可行的方法。
您的解决方案具有指数运行时:每个额外的级别都会产生三次评估,因此您最终会得到O(3 ^ n)个操作和堆栈内存。
答案 1 :(得分:1)
有两种选择:
1)使用离散数学课程并导出公式。复杂性(如果@Sasha提到的话)对于内存和算法都是O(1)。没有循环,没有递归,只有公式。
首先,您需要找到特征多项式并计算其根。让我们假设我们的根是r1,r2,r3,r4。那么第n个元素是F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n
,其中A,B,C,D是一些未知系数。您可以使用初始条件找到这些系数(F(n) = 1
,n <= 3)。
如果你需要,我可以用俄语解释。
2)使用其他变量来存储中间值。就像@ 6052已经回答(他回答得非常快:))。
答案 2 :(得分:0)
只需保留三个变量并滚动它们
a
开始,b
和c
等于1 new_a
都是a + 2*b + c
new_c
为b
,new_b
为a
答案 3 :(得分:0)
以下是这个想法
int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */
for(i=4;i<=n;i++)
{
int next=first+2*second+third;
first=second;
second=third;
third=next;
}
cout<<"The answer is "<<next<<endl;
记忆 O(1),时间 O(n)。
修改强> 你的递归函数确实是指数的,为了使它保持线性,你可以使用 数组 F [n] ,并使用memoization。首先将 F [] 初始化为-1。
int f_rec(int n)
{
if(n>=3)
{
if(F[n]!=-1)return F[n];
F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
return F[n];
}
else
return 1;
}
答案 4 :(得分:0)
有点过分,但可以通过让变量代表在展开的循环中发生变化,与(link)Duff's device结合进入循环来进一步优化:
int f_iter(int n){
int a=1, b=1, c=1;
if(n < 3)
return(1);
switch(n%3){
for( ; n > 2; n -= 3){
case 2:
b = c + 2*a + b;
case 1:
a = b + 2*c + a;
case 0:
c = a + 2*b + c;
}
}
return c;
}