在Java上更快地找到所有自恋(armstrong)数字
有没有更有效的方法? 给定数字N-找到所有在Java上更快地找到所有自恋(armstrong)数字,java,optimization,Java,Optimization,有没有更有效的方法? 给定数字N-找到所有i)断裂; s=s/10; } 如果((int)k==i) 列表.添加(i); } int[]结果=新的int[list.size()]; int i=0; for(int n:list) { 结果[i]=n; i++; } 返回结果;}} 来自(不是我自己的代码) publicstaticbooleanisnac(长x){ 如果(x
public static void main(String args[]) throws Exception
{
long a = System.nanoTime();
int t [] = getNumbers(4_483_647L);
long b = System.nanoTime();
System.out.println("Time totally "+(b-a));
for(int k: t)
System.out.print(k+" ");
}
public static int[] getNumbers(long N)
{
int length=1;
int porog=10, r=1, s=1;
double k;
LinkedList<Integer> list = new LinkedList<>();
for(int i=1; i<N; i++)
{
if(i==porog)
{
length++;
porog*=10;
}
s = i;
k=0;
while(s>0)
{
r = s%10;
k+=Math.pow(r, length);
if(k>i)break;
s=s/10;
}
if((int)k==i)
list.add(i);
}
int[] result = new int[list.size()];
int i=0;
for(int n: list)
{
result[i] = n;
i++;
}
return result; } }
publicstaticvoidmain(字符串args[])引发异常
{
long a=System.nanoTime();
int t[]=getNumbers(4_483_647L);
long b=System.nanoTime();
System.out.println(“总时间”+(b-a));
for(int k:t)
系统输出打印(k+“”);
}
公共静态int[]getNumbers(长N)
{
整数长度=1;
int porog=10,r=1,s=1;
双k;
LinkedList=新建LinkedList();
对于(int i=1;i0)
{
r=s%10;
k+=数学功率(r,长度);
如果(k>i)断裂;
s=s/10;
}
如果((int)k==i)
列表.添加(i);
}
int[]结果=新的int[list.size()];
int i=0;
for(int n:list)
{
结果[i]=n;
i++;
}
返回结果;}}
来自(不是我自己的代码)
publicstaticbooleanisnac(长x){
如果(x<0)返回false;
字符串xStr=Long.toString(x);
int m=xStr.length();
长和=0;
for(char c:xStr.toCharArray()){
总和+=数学功率(字符数字(c,10),m);
}
返回和==x;
}
一些观察结果:
- 如果你的初始最大值是一个
,那么你的结果也应该是long
类型,以防万一(long
适合你,因为自恋的数字相距很远)int
- 如果将返回类型更改为“大”
,则可以使用Long
将结果重新打包到数组中Collections.toArray()
- …虽然实际上,您应该返回链接列表
- 你不需要不断地重新计算能力。对于外循环中的每个十年,您只需要i^j,其中i=0..9,j是当前十年中的位数
- 事实上,您根本不需要
,因为您可以在每十年使用乘法Math.pow()
public static Long[] getNumbers(long N) {
int porog = 10;
LinkedList<Long> list = new LinkedList<>();
// initial powers for the number 0-9
long[] powers = { 0l, 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l };
for (long i = 1; i < N; i++) {
if (i == porog) {
porog *= 10;
// calculate i^length
for (int pi = 1; pi < 10; pi++) {
powers[pi] *= pi;
}
}
long s = i;
long k = 0;
while (s > 0) {
int r = (int)(s % 10);
k += powers[r];
if (k > i)
break;
s /= 10;
}
if (k == i)
list.add(i);
}
return list.toArray(new Long[]{});
}
publicstaticlong[]getNumbers(长N){
int porog=10;
LinkedList=新建LinkedList();
//数字0-9的初始功率
长[]幂={0l,1l,2l,3l,4l,5l,6l,7l,8l,9l};
用于(长i=1;i0){
int r=(int)(s%10);
k+=幂[r];
如果(k>i)
打破
s/=10;
}
如果(k==i)
列表.添加(i);
}
return list.toArray(新的Long[]{});
}
主要的优化是不检查1..N范围内的所有数字。看一看。生成阿姆斯特朗号码的效率很高。例如,所有整数都可以在10-15毫秒内生成
我们可能会注意到,对于每个多组数字,如[1,1,2,4,5,7,7]
,只有一个幂和,而幂和可以由集合中的数字表示,也可以不表示。在示例中,1^7+1^7+2^7+4^7+5^7+7^7+7^7=1741725
,可以用数字表示,因此是阿姆斯特朗数
基于这一考虑,我们可以构建一个算法
对于从1到N的每个数字长度
生成所有可能的多组N
数字
对于每个多集,计算位数^N的和
检查是否可以表示我们在步骤4中得到的数字
多重集合中的数字
如果是-将编号添加到结果列表中
为每个长度N
计算的案例数量等于组合的数量(N+9,9)=(N+9)/(9!N!)
。因此,对于小于10的所有Ns
而言,我们将仅生成92377个多集。因为N我不是专业的编码员,只是自学成才,没有工作经验,所以如果我的代码有点马虎,我道歉
我采用了dovetalk的解决方案,1)自己编写,以便更好地理解它b)进行了一些调整,大大提高了大量数据的运行时间。我希望这能帮助其他寻求帮助解决此问题的人:
public static long[] getNumbers(long N) {
long tempII = N;
LinkedHashSet<Long> narcNums = new LinkedHashSet<>();
long tempResult;
long digitLengthTemp = 10;
long tempI;
long[] powers = {0l, 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l};
for (long i = 0; i < N; i++) {
if (i == digitLengthTemp) {
digitLengthTemp *= 10;
for (short x = 2; x < powers.length; x++) powers[x] *= x;
}
//set value of top digits of numbers past first 3 to a remedial value
tempI = i;
long remedialValue = 0;
tempI /= 10; tempI /= 10; tempI /= 10;
while (tempI > 0) {
short index = (short) (tempI % 10);
remedialValue += powers[index];
tempI /= 10;
}
//only passes 1000 at a time to this loop and adds each result to remedial top half
for (int j = 0; j < (tempII > 1000 ? 1000 : tempII); j++) {
//sets digit length and increases the values in array
if (i == 0 && j == digitLengthTemp) {
digitLengthTemp *= 10;
for (short x = 2; x < powers.length; x++) powers[x] *= x;
}
//resets temp results
tempResult = remedialValue;
tempI = j;
//gets the sum of each (digit^numberLength) of number passed to it
while (tempI > 0) {
if (tempResult > i + j) break;
short index = (short) (tempI % 10);
tempResult += powers[index];
tempI /= 10;
}
//checks if sum equals original number
if (i + j == tempResult) narcNums.add(i + j);
}
i += 999; // adds to i in increments of 1000
tempII -= 1000;
}
//converts to long array
long[] results = new long[narcNums.size()];
short i = 0;
for (long x : narcNums) {
results[i++] = x;
}
return results;
}
publicstaticlong[]getNumbers(长N){
长tempII=N;
LinkedHashSet Nacnums=新LinkedHashSet();
长期结果;
长数字长度=10;
长节拍;
长[]幂={0l,1l,2l,3l,4l,5l,6l,7l,8l,9l};
用于(长i=0;i0){
短期指数=(短期)(tempI%10);
修正值+=幂[指数];
tempI/=10;
}
//一次仅通过1000次循环,并将每个结果添加到上半部分
对于(int j=0;j<(tempII>1000?1000:tempII);j++){
//设置数字长度并增加数组中的值
如果(i==0&&j==digitLengthTemp){
数字长度温度*=10;
对于(短x=2;x public static long[] getNumbers(long N) {
long tempII = N;
LinkedHashSet<Long> narcNums = new LinkedHashSet<>();
long tempResult;
long digitLengthTemp = 10;
long tempI;
long[] powers = {0l, 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l};
for (long i = 0; i < N; i++) {
if (i == digitLengthTemp) {
digitLengthTemp *= 10;
for (short x = 2; x < powers.length; x++) powers[x] *= x;
}
//set value of top digits of numbers past first 3 to a remedial value
tempI = i;
long remedialValue = 0;
tempI /= 10; tempI /= 10; tempI /= 10;
while (tempI > 0) {
short index = (short) (tempI % 10);
remedialValue += powers[index];
tempI /= 10;
}
//only passes 1000 at a time to this loop and adds each result to remedial top half
for (int j = 0; j < (tempII > 1000 ? 1000 : tempII); j++) {
//sets digit length and increases the values in array
if (i == 0 && j == digitLengthTemp) {
digitLengthTemp *= 10;
for (short x = 2; x < powers.length; x++) powers[x] *= x;
}
//resets temp results
tempResult = remedialValue;
tempI = j;
//gets the sum of each (digit^numberLength) of number passed to it
while (tempI > 0) {
if (tempResult > i + j) break;
short index = (short) (tempI % 10);
tempResult += powers[index];
tempI /= 10;
}
//checks if sum equals original number
if (i + j == tempResult) narcNums.add(i + j);
}
i += 999; // adds to i in increments of 1000
tempII -= 1000;
}
//converts to long array
long[] results = new long[narcNums.size()];
short i = 0;
for (long x : narcNums) {
results[i++] = x;
}
return results;
}