我现在正在解决Collatz序列问题。如果我们从1,...,1000000范围内的数字开始,我必须找到最长的Collatz序列。数字n的Collatz序列定义为: 如果n mod 2 == 0则下一个数字是n / 2。如果n mod 2!= 0,那么下一个数字是3 * n + 1。 n = 10的顺序是10,5,16,8,4,2,1。
当然,如果我们以天真的方式解决这个问题,我们会计算每个数字n的Collatz序列在1,...,1000000之间,并检查哪个序列最长。但这并不高效。
更聪明的算法是使用给定Collatz序列的事实,通过不查看前几个元素获得的序列也是Collatz序列。因此,如果我们计算n = 10的序列,即10,5,16,8,4,2,1那么序列5,16,8,4,2,1也是一个Collatz序列,我们立即找到了长度通过计算n = 10的序列,得到n = 5,n = 16,n = 8,n = 4,n = 2和n = 1的Collatz序列。
考虑到这个想法,我使用指针和递归在C中编写了以下代码。
#include <stdio.h>
#include <stdlib.h>
int recursion(int n, int *array){
if((*array)[n]==0){//check if I already have the length of the sequence for this n
if(n/2==(double)n/(double)2){//check if n mod 2 == 0
(*array)[n]=recursion(n/2,array)+1;
}
else{
(*array)[n]=recursion(3*n+1,array)+1;
}
}
else{
return 0;
}
}
int main(int argc, char **argv){
int length[100];//this array will contain the lengths of sequences,
//I will only do it for n=1 up to n=10, but I have to have a bigger
//array since the Collatz sequence elements can be higher than 10
for (int i=0;i<100;i++){
length[i]=0;
}
length[0]=1;//the Collatz sequence for n=1 has length 1
for(int n=1; n<=10;i++){
recursion(n,&length);//use the function for each n
}
for(int i=0;i<10;i++){
printf("%d\n",length[i]);
}
return 0;
}
如果我编译此代码,我会收到几个错误:
main.c:5:13: error: subscripted value is not an array, pointer, or vector
if((*array)[n]==0){
~~~~~~~~^~
main.c:7:12: error: subscripted value is not an array, pointer, or vector
(*array)[n]=recursion(n/2,array)+1;
~~~~~~~~^~
main.c:10:12: error: subscripted value is not an array, pointer, or vector
(*array)[n]=recursion(3*n+1,array)+1;
~~~~~~~~^~
main.c:25:15: warning: incompatible pointer types passing 'int (*)[100]' to
parameter of type 'int *' [-Wincompatible-pointer-types]
recursion(i,&length);
^~~~~~~
main.c:4:27: note: passing argument to parameter 'array' here
int recursion(int n, int *array){
我不知道为什么会收到这些警告和错误。
答案 0 :(得分:3)
array
是int*
。因此,*array
是int
。你不能说int i; i[0]
,那你为什么能说(*array)[0]
?
只需通过array[n]
代替(*array)[n]
,即可正常访问。
另外,在main
功能中,使用recursion
拨打recursion(n, length);
,而不是recursion(n, &length);
。您将数组传递给数组,而不是指针。
答案 1 :(得分:2)
我认为你必须像这样调用这个函数
recursion(n,length);
因为,数组名称包含数组的第一个元素的地址。
你也在pointer to int
收到它。因此,您可以在函数中正常使用array[]
。与array[n]
答案 2 :(得分:1)
使用array[n]
或(*array)[n]
代替n
来访问length
变量。
由于for(int n=1; n<=10;i++){
是一个数组,因此仅使用名称调用该函数会将其传递给地址。
for循环中的小错误。 for(int n=1; n<=10;n++){
至#include <stdio.h>
#include <stdlib.h>
int recursion(int n, int *array){
if(*(array + n)==0){//check if I already have the length of the sequence for this n
if(n/2==(double)n/(double)2){//check if n mod 2 == 0
*(array + n)=recursion(n/2,array)+1;
}
else{
*(array + n)=recursion(3*n+1,array)+1;
}
}
else{
return 0;
}
}
int main(int argc, char **argv){
int length[100];//this array will contain the lengths of sequences,
//I will only do it for n=1 up to n=10, but I have to have a bigger
//array since the Collatz sequence elements can be higher than 10
for (int i=0;i<100;i++){
length[i]=0;
}
length[0]=1;//the Collatz sequence for n=1 has length 1
for(int n=1; n<=10;n++){
recursion(n,length);//use the function for each n
}
for(int i=0;i<10;i++){
printf("%d\n",length[i]);
}
return 0;
}
这些更改修复了编译错误。
db.UserStatistics