利用Java快速查找21位花朵数示例代码
前言
本文主要给大家介绍了关于利用Java快速查找21位花朵数的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
以前备赛的时候遇到的算法题,求所有21位花朵数,分享一下,供大家参考,效率已经很高了。
示例代码
packagecom.jianggujin; importjava.math.BigInteger; importjava.util.ArrayList; importjava.util.List; /** *水仙花数 * *@authorjianggujin * */ publicclassNarcissusNumber { /** *记录10的0~N次方 */ privateBigInteger[]powerOf10; /** *记录0到9中任意数字i的N次方乘以i出现的次数j的结果(i^N*j) */ privateBigInteger[][]preTable1; /** *记录离PreTable中对应数最近的10的k次方 */ privateint[][]preTable2; /** *记录0到9中每个数出现的次数 */ privateint[]selected=newint[10]; /** *记录水仙花数的位数 */ privateintlength; /** *记录水仙花数 */ privateListresults; /** *记录当前的进制 */ privateintnumberSystem=10; /** *@paramn *水仙花数的位数 */ privateNarcissusNumber(intn) { powerOf10=newBigInteger[n+1]; powerOf10[0]=BigInteger.ONE; length=n; results=newArrayList (); //初始化powerPowerOf10 for(inti=1;i<=n;i++) { powerOf10[i]=powerOf10[i-1].multiply(BigInteger.TEN); } preTable1=newBigInteger[numberSystem][n+1]; preTable2=newint[numberSystem][n+1]; //preTable[i][j]0-i的N次方出现0-j次的值 for(inti=0;i =0;k--) { if(powerOf10[k].compareTo(preTable1[i][j])<0) { preTable2[i][j]=k; break; } } } } } publicstaticList search(intnum) { NarcissusNumbernarcissusNumber=newNarcissusNumber(num); narcissusNumber.search(narcissusNumber.numberSystem-1,BigInteger.ZERO,narcissusNumber.length); returnnarcissusNumber.getResults(); } /** *@paramcurrentIndex *记录当前正在选择的数字(0~9) *@paramsum *记录当前值(如选了3个9、2个8就是9^N*3+8^N*2) *@paramremainCount *记录还可选择多少数 */ privatevoidsearch(intcurrentIndex,BigIntegersum,intremainCount) { if(sum.compareTo(powerOf10[length])>=0) { return; } if(remainCount==0) { //没数可选时 if(sum.compareTo(powerOf10[length-1])>0&&check(sum)) { results.add(sum); } return; } if(!preCheck(currentIndex,sum,remainCount)) { return; } if(sum.add(preTable1[currentIndex][remainCount]).compareTo(powerOf10[length-1])<0)//见结束条件2 { return; } if(currentIndex==0) { //选到0这个数时的处理 selected[0]=remainCount; search(-1,sum,0); } else { for(inti=0;i<=remainCount;i++) { //穷举所选数可能出现的情况 selected[currentIndex]=i; search(currentIndex-1,sum.add(preTable1[currentIndex][i]),remainCount-i); } } //到这里说明所选数currentIndex的所有情况都遍历了 selected[currentIndex]=0; } /** *@paramcurrentIndex *记录当前正在选择的数字(0~9) *@paramsum *记录当前值(如选了3个9、2个8就是9^N*3+8^N*2) *@paramremainCount *记录还可选择多少数 *@return如果当前值符合条件返回true */ privatebooleanpreCheck(intcurrentIndex,BigIntegersum,intremainCount) { if(sum.compareTo(preTable1[currentIndex][remainCount])<0)//判断当前值是否小于PreTable中对应元素的值 { returntrue;//说明还有很多数没选 } BigIntegermax=sum.add(preTable1[currentIndex][remainCount]);//当前情况的最大值 max=max.divide(powerOf10[preTable2[currentIndex][remainCount]]);//取前面一部分比较 sum=sum.divide(powerOf10[preTable2[currentIndex][remainCount]]); while(!max.equals(sum)) { //检验sum和max首部是否有相同的部分 max=max.divide(BigInteger.TEN); sum=sum.divide(BigInteger.TEN); } if(max.equals(BigInteger.ZERO))//无相同部分 { returntrue; } int[]counter=getCounter(max); for(inti=9;i>currentIndex;i--) { if(counter[i]>selected[i])//见结束条件3 { returnfalse; } } for(inti=0;i<=currentIndex;i++) { remainCount-=counter[i]; } returnremainCount>=0;//见结束条件4 } /** *检查sum是否是花朵数 * *@paramsum *记录当前值(如选了3个9、2个8就是9^N*3+8^N*2) *@return如果sum存在于所选集合中返回true */ privatebooleancheck(BigIntegersum) { int[]counter=getCounter(sum); for(inti=0;i getResults() { returnresults; } publicstaticvoidmain(String[]args) { intnum=21; System.err.println("正在求解"+num+"位花朵数"); longtime=System.nanoTime(); List results=NarcissusNumber.search(num); time=System.nanoTime()-time; System.err.println("求解时间:\t"+time/1000000000.0+"s"); System.err.println("求解结果:\t"+results); } }
运行查看结果:
正在求解21位花朵数
求解时间:0.327537257s
求解结果:[128468643043731391252,449177399146038697307]
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。