我编写了一个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;
}
谢谢。
答案 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));
}
但是,您很快就会发现即使是n
的适度值,您的实现也很慢:在非常快的硬件上打印42个元素需要超过5秒,而打印100个元素会让您等待很长一段时间。
这是因为您一遍又一遍地在递归调用中重新计算相同的值。相反,您应该计算一次每个值,并在所有后续计算中使用其值。
如果您想保持递归,请使用memoization。 Othrewise,重构您的算法以使用dynamic programming方法。
编写这两种方法中的任何一种都具有非常高的指导价值,因此我建议实施不会破坏它。