A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 hejinzhong 于 2014-8-1 01:06 编辑

* (1)由于1000!的结果太大,无法直接用一个基本数据类型的变量来存储,所以定义一个数组来分别存计算结果的每一位数字。
* (2)计算过程:让每个角标上的数字和相应的乘数相乘并加上前一位的进位。(细节参看 下面calculator 函数)
* (3)遍历数组,查询0的个数。
*
* 举个例子说明计算过程
* 3024 x 15 = 45360(计算器计算结果)
* 每次开始计算进位都为0
* 角标     元素           乘数           上位进位                   运算后该角标值               该位产生的进位
*  0          4       x        15      +         0        =  60                  0                                       6
*  1          2       x        15      +         6       =  36                   6                                       3
*  2          0       x        15      +         3        =  03                  3                                       0
*  3         3        x        15      +        0        =  45                   5                                       4//3024已经算完了,还有进位,多算3位
*  4        0         x        15      +        4        =  04                    4                                       0
*  5        0         x        15      +        0        =  00                     0                                      0
*  6        0        x         15      +        0        =  00                      0                                     0
*  这样在数组中的元素倒着看即为 0045360,当去掉前面0,即为我们需要的运算结果。
*  

  1. public class Test9
  2. {
  3.         private static final int MAX_BOUNDS = 3000;//当角标越界时,可调大该数值
  4.         
  5.         public static void main(String[] args)
  6.         {
  7.                 factorial(1000);//求1000的阶乘
  8.         }
  9.         
  10.         public static void factorial(int num)
  11.         {        
  12.                 int[] arr = new int[MAX_BOUNDS];
  13.                 calculator(arr,num);//计算num的阶乘
  14.                 checkZero(arr);//统计结果中0的个数
  15.         }
  16.         
  17.         private static int[] calculator(int[] arr,int num)
  18.         {
  19.                 arr[0]=1;//将数组中0位元素设为1,任何数和1相乘不影响结果.
  20.                
  21.                 for(int i=1;i<=num;i++)
  22.                 {        
  23.                         int temp = 0,carry = 0;
  24.                         int max = max(arr);
  25.                         
  26.                         for(int j=0;j<max+4;j++)//乘以1000以内的数,增加的长度不超过3,多向后检测3位。
  27.                         {
  28.                                 temp=arr[j]*i+carry;
  29.                                 arr[j]=temp%10;//当前角标值
  30.                                 carry=temp/10;//进位
  31.                         }
  32.                 }
  33.                 return arr;
  34.         }
  35.         
  36.         private static void checkZero(int[] arr)//检测数组中一共有多少个0,最高位开始
  37.         {
  38.                 int count = 0;
  39.                 for(int i=max(arr);i>=0;i--)
  40.                 {
  41.                         if(arr[i]==0)
  42.                                 count++;
  43.                 }
  44.                 System.out.println("共包含0个数:"+count);
  45.         }
  46.         
  47.         private static int max(int[] arr)//检测数组中非0的最大角标
  48.         {
  49.                 for(int max= MAX_BOUNDS-1;max>0;max--)
  50.                 {
  51.                         while(arr[max]!=0)
  52.                                 return max;
  53.                 }
  54.                 return 0;
  55.         }

  56. }
复制代码

14 个回复

倒序浏览
这是我写的http://bbs.itheima.com/thread-133474-1-1.html,思路其实差不多。不用BigInteger的话,我觉得这已经是最简单的思路了,除非从数学上去考虑怎么给出两数相乘的积包含几个0的一般公式。
回复 使用道具 举报
还有就是,这个思路的效率其实还挺让人满意的。至少在算1000!时感觉不出比用BigInteger慢
回复 使用道具 举报
fantacyleo 发表于 2014-8-1 00:56
还有就是,这个思路的效率其实还挺让人满意的。至少在算1000!时感觉不出比用BigInteger慢 ...

我也写了代码,感觉还行,核心点和你基本一样把。代码插不上来。你用的什么浏览器。
回复 使用道具 举报
fantacyleo 发表于 2014-8-1 00:56
还有就是,这个思路的效率其实还挺让人满意的。至少在算1000!时感觉不出比用BigInteger慢 ...

数学考虑只算结尾就简单,但是问题是中间的0产生的可能有点多。
回复 使用道具 举报
hejinzhong 发表于 2014-8-1 00:57
我也写了代码,感觉还行,核心点和你基本一样把。代码插不上来。你用的什么浏览器。 ...

火狐。我怀疑跟浏览器没关系,是论坛的bug。你用“纯文字”模式,直接操作html标签就不会出代码粘贴丢失的问题了
回复 使用道具 举报 1 0
大概看懂了一点。。。不错。。。。牛人。。。
回复 使用道具 举报
看看                             
回复 使用道具 举报
学习了  楼主  大爱
回复 使用道具 举报
都是大神啊,学习了
回复 使用道具 举报
谢谢分享
回复 使用道具 举报
本帖最后由 桂何钢 于 2017-3-25 13:30 编辑

1111111111111
回复 使用道具 举报
楼主思路不错啊!
回复 使用道具 举报
{:3_68:}只要求出每个数能否被5整除,能整除几次,然后记录这个次数,加在一起就是0的个数,因为2×5=10,而2的个数是绝对够用的。
回复 使用道具 举报
烟海 发表于 2014-8-1 22:45
大概看懂了一点。。。不错。。。。牛人。。。

厉害
!!!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马