这是自己第一次独立完整的用递归解决问题,兴奋之余和大家分享。不仅解决3n+1,还能学习递归哦!
题目描述
该数链描述为:如果所给的数n是1,则数链长度为1,结束数链;如果是除1以外的奇数,则n=3*n+1,如果n是偶数,则n=n/2,并继续此过程。
输入
输入多组数据,每行两个数分别是i和j(0<i<=j<10000)。
输出
输出i到j区间中的(包括i和j)数链最长的长度,每行一个。
样例输入
1 10
100 200
201 210
900 1000
样例输出
20
125
89
174
递归版:
#include <stdio.h>
int cnt = 1; // 定义全局计数器
int sum(int n)
{
if (1 == n) // 1直接退出, 递归边界
return cnt;
else if(n%2 == 1) // 奇数
{
sum(3*n + 1);
cnt++;
}
else if (n%2 == 0) // 偶数
{
sum(n/2);
cnt++;
}
return 0;
}
int main()
{
int m, n; // 区间
int temp, temp1; // 记录cnt变量的改变
int i, max; // i循环计数, max每一次比较的最大值
printf("请输入两个数作为区间:");
while (scanf("%d%d", &m, &n) != EOF) // 输入区间[m,n]
{
max = -1; // 初始化最大值为-1保证每一次都更新最大值,此处max<=0都满足
if (m<=0 || m>=10000 || n<=0 || n>=10000)
break;
for (i = m; i <= n; i++)
{ // 由于cnt是全局变量,所以需要用本次的值减去上一次的值,不太好理解
temp = cnt; // 记录上一次的cnt值
sum(i); // 调用递归
temp1 = cnt - temp + 1; // 由于cnt是全局变量,所以需要用本次的值减去上一次的值
if (temp1 > max)
max = temp1;
}
fprintf(stdout, "%d\n", max);
}
}
当时递归一二十分钟就搞定了,关键卡在全局变量cnt的处理,小伙伴们仔细体会,应该还有更好的处理方式的
非递归版不想自己写了,贴上一个大家对比一下吧
非递归版:
#include "stdio.h"
void main()
{
int i,j,k=1,n,flag=1,t,m=1,p;
while (flag)
{
printf("请输入两个数:\n");
scanf("%d %d",&i,&j);
for (t=i;t<=j;t++)
{
n=t;
k=1;
while (n!=1)
{
if (n%2==0)
{
n=n/2;
k=k+1;
}
else
{
n=n*3+1;
k=k+1;
}
}
if (k>m) m=k;
}
printf("%d\n",m);
scanf("%d",&p);
switch(p)
{
case 1: flag=1;
break;
case 0: flag=0;
default:flag=0;
}
m=1;
}
}