Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java上更快地找到所有自恋(armstrong)数字_Java_Optimization - Fatal编程技术网

在Java上更快地找到所有自恋(armstrong)数字

在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

有没有更有效的方法? 给定数字N-找到所有
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()
    ,因为您可以在每十年使用乘法
应用我在上面评论中的想法,并更改方法签名,您可以获得运行速度快30倍的东西:

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;
    }