Introduction
You need to analyze the regular template for the algorithm until approximately the transition to development, which will save a lot of time, for example:
each 1 digit is 1 palindrome, eg: 1 each 2 digits has 1 palindrome, eg: 11. each 3 digits has 10 palindromes, eg: 101,111,...,191. each 4 digits has 10 palindromes, eg: 1001, 1111, ..., 1991. each 5 digits has 100 palindromes, eg: 10001, 11011, ..., 19091, ..., 19991. each 6 digits has 100 palindromes, eg: 100001, 110011, ..., 190091, ..., 199991. each 7 digits has 1000 palindromes, eg: 1000001, ...,1900091,...,1090901, ..., 1999991. each 8 digits has 1000 palindromes, eg: 10000001, ...,19000091,...,10900901, ..., 19999991. ....
then you can write a layout algorithm to implement this.
Implementation
But I can tell you that this implementation can be optimized in the same way as if you used the cache to save palindromes created using palindromes(2) digits, then any high palindromes(n>2) digits palindromes(n>2) can reuse it.
It may not be reliable, but it passes all my tests to github . I left the rest of the work and optimization for you, and I would like you to do it yourself.
private static List<Integer> palindromes(int digits) { return palindromes(digits, 0); } private static List<Integer> palindromes(int digits, int shifts) { List<Integer> result = new ArrayList<>(); int radix = (int) Math.pow(10, digits - 1); int renaming = digits - 2; boolean hasRenaming = renaming > 0; for (int i = start(digits, shifts); i <= 9; i++) { int high = i * radix; int low = low(digits, i); if (hasRenaming) { for (Integer m : palindromes(renaming, shifts + 1)) { int ret = high + m * 10 + low; if (ret < 0) { return result; } result.add(ret); } } else { result.add(high + low); } } return result; } private static int low(int digits, int high) { return digits > 1 ? high : 0; } private static int start(int digits, int shifts) { return digits > 1 && shifts == 0 ? 1 : 0; }
Using
then you can collect all the palindrome numbers as shown below:
Cost of time:
191ms
Enable Caching
public class Palindromes { private static final int[] startingNonZerosTable = { 0,// 0 0, 1,// 1 2 10, 10,//3 4 100, 100, //5 6 1000, 1000,//7 8 10000, 10000,// 9 10 100000, 100000,//11 12 1000000, 1000000,//13 14 10000000, 10000000,//15 16 100000000, 100000000,//17 18 1000000000, 1000000000//19 20 }; private static final int MAX_DIGIT = 9; private static final int MIN_DIGIT = 0; private static final int RADIX = MAX_DIGIT - MIN_DIGIT + 1; private static final int LONG_MAX_DIGITS = 19; private static volatile long[][] cache = new long[LONG_MAX_DIGITS + 1][]; // includes palindromes(0) ---^ static { cache[0] = new long[0]; cache[1] = new long[]{0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L}; cache[2] = new long[]{0L, 11L, 22L, 33L, 44L, 55L, 66L, 77L, 88L, 99L}; } public static LongStream since1(int end) { return between(1, end); } public static LongStream between(int start, int end) { return IntStream.rangeClosed(start, end) .mapToObj(Palindromes::of) .flatMapToLong(identity()); } public static LongStream of(int digits) { return Arrays.stream(palindromes0(digits)) .skip(startingNonZerosTable[digits]); } private final static long[] palindromes0(int digits) { if (cache[digits] != null) { return cache[digits]; } long[] result = new long[sizeOf(digits)]; int size = 0; long high = (long) Math.pow(RADIX, digits - 1); for (int i = MIN_DIGIT; i <= MAX_DIGIT; i++) { for (long mid : palindromes0(digits - 2)) { long value = i * high + mid * RADIX + i; if (value < 0) {//overflow return cache[digits] = Arrays.copyOf(result, size); } result[size++] = value; } } return cache[digits] = result; } private static int sizeOf(int digits) { return MAX_DIGIT * (int) Math.pow(RADIX, (digits - 1) >>> 1) + startingNonZerosTable[digits]; } // v--- java -Xms1024m -Xmx2048m test.algorithm.Palindromes public static void main(String[] args) { Duration duration = timing(() -> { // palindromes[1..15] ---v LongSummaryStatistics result = since1(15).summaryStatistics(); long max = result.getMax(); long count = result.getCount(); System.out.printf("Max: %d, Count: %d%n", max, count); }); System.out.printf("Time Elapsed:%s%n", duration); // ^--- time elapsed: 4s } private static Duration timing(Runnable task) { long starts = System.currentTimeMillis(); task.run(); return Duration.ofMillis(System.currentTimeMillis() - starts); } }
Cost of time:
palindromes [1..15] elapsed time: 4 s