zoukankan      html  css  js  c++  java
  • 数字黑洞求解问题

    任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456。求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0)。如此往复,数字会落入某个循环圈(称为数字黑洞)。
    比如,刚才的数字会落入:[82962, 75933, 63954, 61974] 这个循环圈。要求编写程序,找到5位数所有可能的循环圈,并输出。

    这是某个比赛中的一个问题,我试着用c语言求了一下。大概思路就是:把五位数拆分,排序,求最大和最小数,求差,再判断是否落入了黑洞数的循环。

    /****************************************
    输出5位数的全部黑洞数 
    *****************************************/
    #include<stdio.h>
    int Max_Min(int num);
    void Find(int num);
    int c[20]={0},k=0;        //这两个全局变量是为了查重 
    void main()
    {
        int num; 
        
        for(num=10000;num<99999;num++)
        {
            Find(num);
        }    
    } 
    /**********************************
    函数名称:Max_Min
    函数功能:把一个五位数的各位提取出来,
              重新组合成最大数和最小数,并求差 
    参数:num--输入的五位数 
    返回值:sub_result--最大数与最小数的差 
    ***********************************/ 
    int Max_Min(int num)
    {
        char i=0,j=0,t;
        int max=0,min=0,sub_result; 
        char a[5];
        for(i=0;i<5;i++)            //把各位数取出来,不足5位的补0 
        {
            a[i]=num%10;
            num=num/10;
        }
        for(i=0;i<=3;i++)            //从大到小排序 
            for(j=0;j<=3-i;j++)
            {
                if(a[j]<a[j+1])
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        for(i=0;i<=4;i++)
        {
            max=max*10+a[i];        //组成的最大的数 
        }
        for(i=4;i>=0;i--)
        {
            min=min*10+a[i];        //组成的最小的数 
        }
        sub_result=max-min;            //求差 
        return sub_result; 
    }
    /*********************************
    函数名称:Find 
    函数功能:判断输入的数是否有黑洞数,并输出
    参数:num--输入的五位数 
    **********************************/
    void Find(int num)
    {
        char i,j,m,flag=0;
        int b[100]; 
        b[0]=Max_Min(num);
        for(i=1;i<100;i++)                //测试前100个
        {
            b[i]=Max_Min(b[i-1]);         
            for(j=0;j<i;j++)
            {
                if(b[j]==b[i])
                {
                    flag=1;
                    for(m=0;m<20;m++)    //查看前面是否已经输出过 
                    {
                        if(b[j]==c[m])
                        {
                            flag=0;
                            break;
                        }
                    }
                    break;
                }    
            }
            if(flag==1)                    //存在黑洞数并且前面没有输出过 
            {
                printf("%c",'[');
                for(;j<i-1;j++)
                {
                    printf("%d%c",b[j],',');
                    c[k++]=b[j];    
                }
                printf("%d",b[j]);
                c[k++]=b[j];
                    
                printf("%c",']');
                printf("
    ");
                return ;
            }
        }
    }

    这段程序很多不足之处,比如在对最大和最小数求差的时候,只求了100次,当然算出来结果也是对的,因为五位数的黑洞数都能在100次之内被检测出来,其实实际情况远远用不了100次。结果虽然对,但思路总归不严谨。下面给出一个用递归法求解的。

    #include<stdio.h>
    int Max_Min(int num);
    void Find(int num);
    int record1[50]={0},k=0;        //这两个全局变量是为了查重 
    int record2[100],f;                //每次使用前清零 
    void main()
    {
        int num; 
        char m;
        for(num=10000;num<=99999;num++)
        {
            
            Find(num); 
            for(m=0;m<100;m++)            //由于是全局变量,在本次使用后清零 
            {
                record2[m]=0;
            }
            f=0;
        }    
    } 
    /**********************************
    函数名称:Max_Min
    函数功能:把一个五位数的各位提取出来,
              重新组合成最大数和最小数,并求差 
    参数:num--输入的五位数 
    返回值:sub_result--最大数与最小数的差 
    ***********************************/ 
    int Max_Min(int num)
    {
        char i=0,j=0,t;
        int max=0,min=0,sub_result; 
        char a[5];
        for(i=0;i<5;i++)            //把各位数取出来,不足5位的补0 
        {
            a[i]=num%10;
            num=num/10;
        }
        for(i=0;i<=3;i++)            //从大到小排序,冒泡法排序 
            for(j=0;j<=3-i;j++)
            {
                if(a[j]<a[j+1])
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        for(i=0;i<=4;i++)
        {
            max=max*10+a[i];        //组成的最大的数 
        }
        for(i=4;i>=0;i--)
        {
            min=min*10+a[i];        //组成的最小的数 
        }
        sub_result=max-min;            //求差 
        return sub_result; 
    }
    /*********************************
    函数名称:Find 
    函数功能:判断输入的数是否有黑洞数,并输出
    参数:num--输入的五位数 
    **********************************/
    void Find(int num)
    {
        char i,j,m;
        int n;
        n=Max_Min(num);
        for(i=0;i<f;i++)
        {
            if(n==record2[i])            //检测黑洞数 
            {
                for(j=0;j<50;j++)        //检测是否已经输出过 
                {
                    if(n==record1[j])
                    {    
                        return;            //前面已经输出过,退出函数 
                    }
                } 
                printf("%c",'[');
                for(j=i;j<f-1;j++)                    //将黑洞数输出 
                {
                    printf("%d%c",record2[j],',');
                    record1[k++]=record2[j];        //记录,为下次输出查重 
                }
                printf("%d",record2[j]);
                record1[k++]=record2[j];            //记录,为下次输出查重
                printf("%c",']');
                printf("
    ");
                
                return;                    //输出完毕,退出 
            }
        }
        record2[f++]=n;
        
        Find(n);        //递归调用 
    }

    这段代码用了递归调用,可以一直求最大值与最小值的差直到出现循环。这种思路就比前面的那种要好很多。输出结果如下:

    当然这段代码还有些问题,虽然可以输出正确结果,但是效率不高,从10000检测到99999要把所有的5位数都检测一遍,很复杂。不过现在我还没想到更高效率的解法,以后努力吧。

  • 相关阅读:
    有关类成员变量和局部成员变量初始值设置问题
    Redis在windows下安装与配置
    java内存区域-方法区
    Java中的反射机制(一)
    (转)Spring实现IoC的多种方式
    UUID
    Python os.path
    Leetcode 215、数组中第k个最大的元素
    树的非递归遍历
    About MySQL
  • 原文地址:https://www.cnblogs.com/Atsea/p/3523695.html
Copyright © 2011-2022 走看看