《入门经典》——6.23
6174问题:
假设你有各位数字不相同的四位数,把所有数字从大到小排序后得到a,从小到大排序后得到b,然后用a-b替换原来这个数,并继续操作。例如,从1234出发,依次可以得到4321-1234 = 3087、8730-378=8352、8532-2358=6174.有趣的是,7641-1467=6174,回到了它自己。
输入一个n位数,输出操作序列,直到出现循环(即新得到的数曾经得到过)。输入保证在循环之前最多只会产生1000个整数。
样例输入:1234
样例输出:1234->3087->8352->6174->6174
分析:这道问题我们应该解决两个关键问题,如何得到每次操作后的数以及如何判断这个数是否曾经出现过。
如何得到操作后得到的数?在这个问题中,我们进行字符串和整数的转化、排序等,这里我们用到c语言语法中实现字符串和整型相互读入的两个函数——sscanf和sprintf。而对于排序,这里数据较小手写一个冒泡即可。
如何判断这个数是否曾静出现过?很简单,我们先用一个数组来记录出现过的数字,然后每当完成一次操作得到一个新的数字,我们都在原先这个数组中进行一个检索,判断这个新生成的数字是否曾经出现过。
简单的参考代码如下:
#include<cstdio> #include<cstring> using namespace std; int get_next(int x)//计算整数x进行一次变换得到的整数 { char s[10]; int Min , Max; sprintf(s,"%d",x); int len = strlen(s); for(int i = 0;i < len-1;i++)//由小到大 for(int j = i+1;j < len;j++) { if(s[i] > s[j]) { char t = s[i]; s[i] = s[j]; s[j] = t; } } sscanf(s,"%d",&Min); for(int i = 0;i < len/2;i++)//反转 { char t = s[i]; s[i] = s[len-1-i]; s[len-1-i] = t; } sscanf(s,"%d",&Max); return Max - Min; } int main() { int num[105]; memset(num , 0 , sizeof(num)); int index = 1; scanf("%d",&num[0]); printf("%d",num[0]); while(1) { int found = 0;//假设一开始没有出现循环 num[index] = get_next(num[index-1]); printf("->%d",num[index]); for(int i = 0;i < index;i++)//检索是否出现过 if(num[i] == num[index]) {found = 1;break;} index++; if(found) break; else continue; } return 0; }