从递归到迭代函数

时间:2015-01-05 23:21:15

标签: c recursion

我试图从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,如果我错了,请纠正我。

谢谢

5 个答案:

答案 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开始,bc等于1
  • 每个步骤new_a都是a + 2*b + c
  • 翻转:new_cbnew_ba
  • 重复所需的步骤数

答案 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;
}