这是自己第一次独立完整的用递归解决问题,兴奋之余和大家分享。不仅解决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; } }