При попытке валидации думает секунд 30 и дает TimeOut валидации.
При тесте на MAX_VALUE дает около 15 секунд на моем стареньком Celeron 2,6 ГГц. Все процессы оптимизировал как мог в соответствии с рекомендациями, куда дальше копать уже не вижу вариантов (только если вызов отдельных методов включить в тело getNumbers, но по моим тестам это вообще не влияет на скорость).
Вопрос - timeout связан с тем, что расчет происходит слишком долго ( в таком случае логично было бы вывести ошибку, что превышено время, а не просто, что все зависло), либо есть еще какой-то баг, который я не замечаю?
package com.javarush.task.task20.task2025;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/*
Алгоритмы-числа
*/
public class Solution {
public static byte cursor = 18;//max 18
public static byte leng = (byte) (cursor + 1);
public static long max;
public static boolean go;
static long[][] pows = new long[11][20];
static {
if (leng < 19) max = (long) Math.pow(10, leng);
else
max = Long.MAX_VALUE;
for (short i = 0; i <= 9; i++) {
for (short j = 0; j <= 19; j++) {
pows[i][j] = (long) Math.pow(i, j);
}
}
for (short j = 0; j <= 19; j++) {
pows[10][j] = 0;
}
}
private static byte[] toByte(long l) {
if (l >= max || l < 0) {
return null;
} else {
byte[] digits = new byte[leng];
for (int i = leng - 1; i >= 0; i--) {
digits[i] = (byte) (l % 10);
if (digits[i] == 0 && l > 0) digits[i] = 10;
l = l / 10;
}
/* for (byte b:digits){
System.out.print(b);
}
System.out.println("");*/
return digits;
}
}
public static long[] getNumbers(long N) {
go = true;
if (N <= Long.MAX_VALUE) {
List<Long> results = new ArrayList<>();
//if (N>0) results.add(0l);
byte[] bytes = new byte[leng];
for (int i = 0; i <= cursor; i++)
bytes[i] = 0;
while (go) {
add_one(bytes);
// for (byte b:bytes){
// System.out.print(b);
// }
// System.out.println("");
//считаем сумму цифр в степени длины числа
long sum = 0;
byte eff_leng = 0;//длина реального числа
for (byte b : bytes) {
if (b != 0) eff_leng++;
}
for (byte number : bytes) {
sum += pows[number][eff_leng];
}
//--считаем сумму цифр в степени длины числа
//проверяем амстронговость числа и возвращаем его в sum
byte[] digits = toByte(sum);//сумму на цифры
if (digits == null || sum >= N) sum = -1;//если длины разные, то уже не сравниваем
else {
int i1 = 0;
while (i1 < leng - 1) {//сортируем цифры по возрастанию
if (digits[i1] <= digits[i1 + 1]) i1++;
else {
byte buf = digits[i1];
digits[i1] = digits[i1 + 1];
digits[i1 + 1] = buf;
i1--;
}
if (i1 < 0) i1 = 0;
}
/*
for (byte b:digits){//блок печати
System.out.print(b);
}
System.out.println(" : "+sum);
*/
for (i1 = 0; i1 < leng; i1++) {
if (digits[i1] != bytes[i1]) {
sum = -1;
break;
}
}
}
//--проверяем амстронговость числа и возвращаем его в sum, либо -1
if (sum > 0) results.add(sum);
}
long[] result = new long[results.size()];
short i;
for (i = 0; i < results.size(); i++) {
result[i] = results.get(i);
}
i = 0;
long buf;
while (i < result.length - 1) {
if (result[i] <= result[i + 1]) i++;
else {
buf = result[i];
result[i] = result[i + 1];
result[i + 1] = buf;
i--;
}
}
return result;
}
long[] temp = new long[0];
return temp;
}
private static void add_one(byte[] bytes) {
if (cursor >= 0) {
bytes[cursor]++;
if (bytes[cursor] > 10) {
cursor--;
add_one(bytes);
cursor++;
if (cursor > 0) bytes[cursor] = bytes[cursor - 1];
}
} else {
go = false;
bytes[0] = 0;
}
}
public static void main(String[] args) {
// Date start = new Date();
// long[] testValues = new long[]{200, Long.MAX_VALUE};
// for (long testValue : testValues) {
// long[] l = getNumbers(testValue);
// System.out.print("For "+testValue+":");
// for (long l1 : l) {
// System.out.print(l1 + "; ");
// }
// System.out.println();
// }
// Date finish = new Date();
// System.out.println("Spent " + (finish.getTime() - start.getTime() + " ms."));
}
}