C:具有递归的Hofstadter Q序列

时间:2016-11-08 17:58:35

标签: c recursion

我编写了一个C函数,通过递归在屏幕上打印出Hofstadter Q序列的前N个元素。

Hofstadter Q序列定义是:

  

Q(1)= Q(2)= 2

     

Q(n)= Q(n-Q(n-1))+ Q(n-Q(n-2))

我的代码应该没问题,但我不知道在哪里放printf来打印结果。

第一个数字是:1,1,2,3,3,4,5,5,6,6,8,8,8,10,9,10,11,11,12,12,12 ,12,16,14,14,16,16,16,16,20,17,17,20,21,19,20,22,21,22,23,23,24,24,24,24,24 ,32,24,25,30,28,26,30,30等。

我的代码实际上是:

#include <stdio.h>
int hof(int n);

int main()
{
    int n;
    int flag;

    printf("How many elements to print: ");
    scanf("%d",&n);

    flag=hof(n);

    return 0;
}

int hof(int n) {
    int res;

    if (n < 3) res = 1;
    else res=hof(n-(hof(n-1)))+hof(n-(hof(n-2)));

    return res;
}

谢谢。

2 个答案:

答案 0 :(得分:1)

您的代码重复计算同一组子序列。这意味着它效率低下,代码中没有一个地方可以“插入”printf。

使用memoization,可以完成:

#include <stdio.h>
int arr[512];

int hof(int n);
int main(void) {

    int n;
    int flag;

    printf("How many elements to print: ");
    scanf("%d",&n);

    flag=hof(n);

    for(size_t i = 1; arr[i]; i++)
        printf("%d ", arr[i]);

    return 0;
}

int hof(int n){
    int res;

    if (arr[n]) return arr[n];

    if (n < 3) res = 1;
    else res=hof(n-(hof(n-1)))+hof(n-(hof(n-2)));

    arr[n] = res;
    return res;
}

您可以根据需要更改数组大小,或使用malloc()动态分配。

答案 1 :(得分:0)

printf的调用进入循环:

for (int i = 1 ; i < n ; i++) {
    printf("%d ", hof(i));
}

Demo.

但是,您很快就会发现即使是n的适度值,您的实现也很慢:在非常快的硬件上打印42个元素需要超过5秒,而打印100个元素会让您等待很长一段时间。

这是因为您一遍又一遍地在递归调用中重新计算相同的值。相反,您应该计算一次每个值,并在所有后续计算中使用其值。

如果您想保持递归,请使用memoization。 Othrewise,重构您的算法以使用dynamic programming方法。

编写这两种方法中的任何一种都具有非常高的指导价值,因此我建议实施不会破坏它。