Лучший алгоритм для поиска следующего палиндрома числовой строки

Во-первых, вот проблема:

Натуральное число называется палиндромом, если его представление в десятичной системе одинаково при чтении слева направо и справа налево. Для заданного положительного целого числа K, состоящего не более чем из 1 000 000 цифр, выведите значение наименьшего палиндрома, превышающего K, в выходной файл. Числа всегда отображаются без ведущих нулей.

Вход: Первая строка содержит целое число t — количество тестов. Целые числа K даны в следующих t строках.

Выходные данные: для каждого K выведите наименьший палиндром, больший, чем K. Пример

Вход:

2

808

2133

Вывод:

818

2222

Во-вторых, вот мой код:

// I know it is bad practice to not cater for erroneous input,
// however for the purpose of the execise it is omitted
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.lang.Exception;
import java.math.BigInteger;

public class Main
{    
    public static void main(String [] args){   
        try{
            Main instance = new Main(); // create an instance to access non-static
                                        // variables
        
            // Use java.util.Scanner to scan the get the input and initialise the
            // variable
            Scanner sc=null;

            BufferedReader r = new BufferedReader(new InputStreamReader(System.in));

            String input = "";

            int numberOfTests = 0;

            String k; // declare any other variables here
            
            if((input = r.readLine()) != null){
                sc = new Scanner(input);
                numberOfTests = sc.nextInt();
            }

            for (int i = 0; i < numberOfTests; i++){
                if((input = r.readLine()) != null){
                    sc = new Scanner(input);
                    k=sc.next(); // initialise the remainder of the variables sc.next()
                    instance.palindrome(k);
                } //if
            }// for
        }// try

        catch (Exception e)
        {
            e.printStackTrace();
        }
    }// main

    public void palindrome(String number){

        StringBuffer theNumber = new StringBuffer(number);
        int length = theNumber.length();
        int left, right, leftPos, rightPos;
        // if incresing a value to more than 9 the value to left (offset) need incrementing
        int offset, offsetPos;
        boolean offsetUpdated;
        // To update the string with new values
        String insert;
        boolean hasAltered = false;

        for(int i = 0; i < length/2; i++){
            leftPos = i; 
            rightPos = (length-1) - i;
            offsetPos = rightPos -1; offsetUpdated = false;
            
            // set values at opposite indices and offset
            left = Integer.parseInt(String.valueOf(theNumber.charAt(leftPos)));
            right = Integer.parseInt(String.valueOf(theNumber.charAt(rightPos)));
            offset = Integer.parseInt(String.valueOf(theNumber.charAt(offsetPos)));

            if(left != right){
                // if r > l then offest needs updating
                if(right > left){
                    // update and replace
                    right = left;
                    insert = Integer.toString(right);

                    theNumber.replace(rightPos, rightPos + 1, insert);
                
                    offset++; if (offset == 10) offset = 0;
                    insert = Integer.toString(offset);

                    theNumber.replace(offsetPos, offsetPos + 1, insert);
                    offsetUpdated = true;
               
                    // then we need to update the value to left again
                    while (offset == 0 && offsetUpdated){ 
                        offsetPos--;
                        offset =
                            Integer.parseInt(String.valueOf(theNumber.charAt(offsetPos)));
                        offset++; if (offset == 10) offset = 0;
                        // replace
                        insert = Integer.toString(offset);
                        theNumber.replace(offsetPos, offsetPos + 1, insert);
                    }
                    // finally incase right and offset are the two middle values
                    left = Integer.parseInt(String.valueOf(theNumber.charAt(leftPos)));
                    if (right != left){
                        right = left;
                        insert = Integer.toString(right);
                        theNumber.replace(rightPos, rightPos + 1, insert);
                    }
                }// if r > l
                else
                    // update and replace
                    right = left;
                    insert = Integer.toString(right);
                    theNumber.replace(rightPos, rightPos + 1, insert);           
            }// if l != r
        }// for i
        System.out.println(theNumber.toString());
    }// palindrome
}

Наконец мое объяснение и вопрос.

My code compares either end and then moves in
    if left and right are not equal
        if right is greater than left
            (increasing right past 9 should increase the digit
             to its left i.e 09 ---- > 10) and continue to do
             so if require as for 89999, increasing the right
             most 9 makes the value 90000
        
             before updating my string we check that the right
             and left are equal, because in the middle e.g 78849887
             we set the 9 --> 4 and increase 4 --> 5, so we must cater for this.

Проблема связана с системой онлайн-судей spoj.pl. Мой код работает для всего теста, который может предоставить, но когда я его отправляю, я получаю сообщение об ошибке превышения срока, и мой ответ не принимается.

У кого-нибудь есть какие-либо предложения относительно того, как я могу улучшить свой алгоритм. При написании этого вопроса я подумал, что вместо моего цикла while (offset == 0 && offsetUpdated) я мог бы использовать логическое значение, чтобы убедиться, что я увеличиваю смещение на моей следующей [i] итерации. Подтверждение моего изменения или любое предложение будут оценены, также дайте мне знать, если мне нужно сделать мой вопрос более ясным.


person Mead3000    schedule 28.10.2011    source источник
comment
Ваш код, похоже, не обрабатывает тестовый пример (808 обрабатывается неправильно).   -  person n. 1.8e9-where's-my-share m.    schedule 29.10.2011
comment
очень хороший момент, но добавление одного к входу исправит это, и это не поможет с эффективностью.   -  person Mead3000    schedule 29.10.2011
comment
спасибо, что указали на это, хотя   -  person Mead3000    schedule 29.10.2011


Ответы (10)


Это похоже на много кода. Вы уже пробовали очень наивный подход? Проверить, является ли что-то палиндромом, на самом деле очень просто.

private boolean isPalindrome(int possiblePalindrome) {
    String stringRepresentation = String.valueOf(possiblePalindrome);
    if ( stringRepresentation.equals(stringRepresentation.reverse()) ) {
       return true;
    }
}

Возможно, это не самый производительный код, но он дает вам действительно простую отправную точку:

private int nextLargestPalindrome(int fromNumber) {
    for ( int i = fromNumber + 1; ; i++ ) {
        if ( isPalindrome( i ) ) {
            return i;
        }
    }
}

Теперь, если это недостаточно быстро, вы можете использовать его в качестве эталонной реализации и работать над уменьшением алгоритмической сложности.

На самом деле должен быть способ с постоянным временем (ну, это линейно по количеству цифр ввода) для поиска следующего по величине палиндрома. Я приведу алгоритм, который предполагает, что число состоит из четного числа цифр (но может быть расширено до нечетного числа цифр).

  1. Найдите десятичное представление введенного числа ("2133").
  2. Разделите его на левую половину и правую половину («21», «33»);
  3. Сравните последнюю цифру в левой половине и первую цифру в правой половине.
    a. Если правое больше левого, увеличьте левое и остановитесь. ("22")
    б. Если правая часть меньше левой, остановитесь.
    c. Если правое равно левому, повторите шаг 3 с предпоследней цифрой слева и второй цифрой справа (и так далее).
  4. Возьмите левую половину и добавьте левую половину в обратном порядке. Это ваш следующий по величине палиндром. ("2222")

Применяется к более сложному числу:

1.    1234567887654322
2.    12345678   87654322
3.    12345678   87654322
             ^   ^         equal
3.    12345678   87654322
            ^     ^        equal
3.    12345678   87654322
           ^       ^       equal
3.    12345678   87654322
          ^         ^      equal
3.    12345678   87654322
         ^           ^     equal
3.    12345678   87654322
        ^             ^    equal
3.    12345678   87654322
       ^               ^   equal
3.    12345678   87654322
      ^                 ^  greater than, so increment the left

3.    12345679

4.    1234567997654321  answer

Это немного похоже на описанный вами алгоритм, но он начинается с внутренних цифр и переходит к внешним.

person Mark Peters    schedule 28.10.2011
comment
Число может содержать до 1000000 цифр, поэтому о int не может быть и речи. С вашим алгоритмом я для числа, подобного 8999, увеличивая число во второй половине, должно повлиять на первую половину - person Mead3000; 29.10.2011
comment
@Mead: Это, вероятно, означает, что вы можете исключить наивный подход. Для алгоритма, который я опубликовал, нет ничего, что говорило бы о том, что вам когда-либо нужно хранить эти вещи в виде двоичных чисел. Вы можете просто иметь дело со строками все время. - person Mark Peters; 29.10.2011
comment
Кроме того, для алгоритма, который я опубликовал, я не уверен, какие проблемы возникнут при обработке 8999. В итоге вы увеличите 89 до 90 (начиная с 9>8) и создадите 9009. Однако будут угловые случаи вокруг чего-то вроде 9999, когда количество цифр увеличится. Но я оставлю вам угловые случаи (и работу с нечетными числами). - person Mark Peters; 29.10.2011
comment
@Mark: А как насчет того, когда на выходе больше цифр, чем на входе? Как самый маленький палиндром больше 99 = 101. И отдельно, я думаю, в вашем алгоритме вы принимаете предположение, что во входных данных будет четное количество цифр; я ошибся ? - person Costi Ciudatu; 29.10.2011
comment
@CostiCiudatu: он не проверяет, является ли ввод палиндромом или нет. - person Bhesh Gurung; 29.10.2011
comment
@Mark: я не обновился вовремя, поэтому я не видел вашу домашнюю работу по крайним случаям выше, поэтому игнорируйте вышеизложенное, я все равно удалю ее. - person Costi Ciudatu; 29.10.2011
comment
@BheshGurung: Нет, это не так. Но поскольку вы упомянули об этом, похоже, мой комментарий касается проверки ввода? Может я не так выразился... :-/ - person Costi Ciudatu; 29.10.2011
comment
вы можете улучшить это, если вы разделите всю строку / char черты, перевернете подстроку rhs и сравните их. если правая часть больше, увеличьте левую на единицу. после этого результат будет lhs^lhs_reversed. для нечетных # цифр просто выясните, нужно ли увеличивать средний символ или нет, и сделайте очевидные вещи - person b.buchhold; 29.10.2011
comment
@Mark Peter Hpw, не могли бы вы применить его к номеру, который я указал в вашем ответе 7499996381? - person Mead3000; 29.10.2011
comment
@b.buchhold: К сожалению, это не работает. Рассмотрим 234325. 523 больше 234, поэтому по вашему алгоритму следующим по величине палиндромом должен быть 235532. Это неверно, так как 234432 приходит раньше. - person Mark Peters; 29.10.2011
comment
@Mead: Ты сам пробовал? Где вы столкнулись с проблемой? Мой алгоритм кажется довольно простым для этого. Кроме того, оставьте правки ответа для исправления/улучшения ответа, а не для запроса дополнительной помощи. - person Mark Peters; 29.10.2011
comment
@MarkPeters хорошо, извини. Как вы предлагаете увеличить левую часть, то есть 1. 7493996381 2. 74939 96381 3. 74939 96381 '9' and '9'equal 4. 74939 96481 '3' and '6' so increment the lhs вот где у меня проблемы, я не могу увеличить левое число как десятичное число, потому что оно потенциально может иметь длину 5 * 10 ^ 5 цифр. Мой другой вариант - увеличить последнюю цифру «9», которая затем должна повлиять на «3» (что-то вроде моего использования смещения), а затем снова запустить процесс. Я ошибся? или, увеличив левый, могу ли я просто добавить обратное, чтобы получить свой палиндром? - person Mead3000; 29.10.2011
comment
@ Mead3000: Чтобы увеличить, я бы начал с проверки того, достаточно ли производительно что-то вроде new BigInteger("74939").add(BigInteger.ONE).toString() (поскольку это одноразовая операция, я не думаю, что это так уж плохо). Он может работать с практически неограниченными данными. Если этого недостаточно, вам придется написать собственное посимвольное сложение. Единственное, с чем вам нужно быть осторожным, это то, что если вы в конечном итоге добавите цифру, убедитесь, что вы добавляете не две цифры, отражая их, а только одну. - person Mark Peters; 29.10.2011
comment
Я не вижу никакого метода reverse() в классе String. - person Anirban Nag 'tintinmj'; 06.10.2013
comment
@tintinmj: Вы правы, эта часть была неверной; Я просто пытался дать представление об алгоритме. Вы можете использовать StringBuilder.reverse(), чтобы перевернуть строку. - person Mark Peters; 06.10.2013
comment
Есть ли у вас планы по исправлению вашего ответа для работы с числами более 30 цифр? - person Roland Illig; 20.04.2020
comment
@RolandIllig: Не уверен, что вы имеете в виду, алгоритм, который я включил, будет работать с десятками тысяч цифр. - person Mark Peters; 20.04.2020
comment
Вы правы, алгоритм работает с большими числами. Но фрагменты кода — нет. Я имел в виду фрагменты кода, извините за неточность. - person Roland Illig; 20.04.2020
comment
Не могли бы вы удалить неэффективные фрагменты кода из верхней части вашего ответа? Они не подходят для принятого ответа с таким количеством голосов. - person Roland Illig; 14.06.2020
comment
Пожалуйста, прокомментируйте приведенный ниже случай: вывод 122 будет 222, ожидаемый результат должен быть 131. - person vCillusion; 17.10.2020

Нет смысла возиться с отдельными цифрами, когда единственной необходимой операцией является одно простое сложение. Следующий код основан на ответе Ракса.

В коде намеренно делается упор на простоту, а не на скорость выполнения.

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;
import org.junit.Test;

public class NextPalindromeTest {

    public static String nextPalindrome(String num) {
        int len = num.length();
        String left = num.substring(0, len / 2);
        String middle = num.substring(len / 2, len - len / 2);
        String right = num.substring(len - len / 2);

        if (right.compareTo(reverse(left)) < 0)
            return left + middle + reverse(left);

        String next = new BigInteger(left + middle).add(BigInteger.ONE).toString();
        return next.substring(0, left.length() + middle.length())
             + reverse(next).substring(middle.length());
    }

    private static String reverse(String s) {
        return new StringBuilder(s).reverse().toString();
    }

    @Test
    public void testNextPalindrome() {
        assertEquals("5", nextPalindrome("4"));
        assertEquals("11", nextPalindrome("9"));
        assertEquals("22", nextPalindrome("15"));
        assertEquals("101", nextPalindrome("99"));
        assertEquals("151", nextPalindrome("149"));
        assertEquals("123454321", nextPalindrome("123450000"));
        assertEquals("123464321", nextPalindrome("123454322"));
    }
}
person Roland Illig    schedule 14.09.2017
comment
Это удивительное решение! Большое спасибо!! - person MyName; 15.12.2017
comment
Это такой красивый код. Интересно, почему это не получает голосов? - person Ashish K Agarwal; 14.03.2018
comment
просто для подтверждения, не так ли, что middle.length() всегда будет либо 0 (для четного номера длины), либо 1 (для нечетного номера длины). - person Gautam Tyagi; 08.07.2020
comment
Да, middle.length() всегда равно 0 или 1. - person Roland Illig; 09.07.2020
comment
Один вопрос: почему длина левого и среднего считается в последней строке next.substring(0, left.length() + middle.length())? - person Saurav Sahu; 27.09.2020
comment
@SauravSahu: Как бы вы написали это по-другому? - person Roland Illig; 28.09.2020

Ну, у меня есть решение постоянного порядка (по крайней мере порядка k, где k - количество цифр в числе)

Возьмем несколько примеров, предположим, что n=17208.

делим число на две части от середины и реверсивно записываем старшую часть на меньшую. то есть 17271, если сгенерированное таким образом число больше вашего n, это ваш палиндром, если не просто увеличить центральное число (стержень), то есть вы получите 17371

другие примеры

n = 17286 palidrome-attempt = 17271 (поскольку это меньше, чем n, увеличивает точку поворота, в данном случае 2), поэтому палидром = 17371

n=5684 палидром1=5665 палидром=5775

n=458322 палиндром=458854

теперь предположим, что n = 1219901 palidrome1 = 1219121 увеличение опорной точки делает мое число здесь меньше, поэтому также увеличьте число соседних опорных точек 1220221

и эту логику можно расширить

person Raks    schedule 18.11.2011
comment
Я использовал эту же логику. Однако есть много особых случаев, которые необходимо обработать. Например. что если n=999 или n=22 или n=10920. - person Ashish K Agarwal; 14.03.2018
comment
@AshishKAgarwal Если вы посмотрите на мой код, который реализует этот точный ответ, вы увидите, что одного оператора if достаточно, чтобы охватить все ваши множество частных случаев. - person Roland Illig; 20.11.2018

Вот мой код в java. Вся идея взята из здесь .

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("Enter number of tests: ");
        int t = sc.nextInt();

        for (int i = 0; i < t; i++) {
            System.out.println("Enter number: ");
            String numberToProcess = sc.next(); // ne proveravam dal su brojevi
            nextSmallestPalindrom(numberToProcess);
        }
    }

    private static void nextSmallestPalindrom(String numberToProcess) {
        

        int i, j;

        int length = numberToProcess.length();
        int[] numberAsIntArray = new int[length];
        for (int k = 0; k < length; k++)
            numberAsIntArray[k] = Integer.parseInt(String
                    .valueOf(numberToProcess.charAt(k)));

        numberToProcess = null;

        boolean all9 = true;
        for (int k = 0; k < length; k++) {
            if (numberAsIntArray[k] != 9) {
                all9 = false;
                break;
            }
        }
        // case 1, sve 9ke
        if (all9) {
            whenAll9(length);
            return;
        }

        int mid = length / 2;
        if (length % 2 == 0) {
            i = mid - 1;
            j = mid;
        } else {
            i = mid - 1;
            j = mid + 1;
        }
        
        while (i >= 0 && numberAsIntArray[i] == numberAsIntArray[j]) {
            i--;
            j++;
        }
        // case 2 already polindrom
        if (i == -1) {
            if (length % 2 == 0) {
                i = mid - 1;
                j = mid;
            } else {
                i = mid;
                j = i;
            }
            addOneToMiddleWithCarry(numberAsIntArray, i, j, true);

        } else {
            // case 3 not polindrom
            if (numberAsIntArray[i] > numberAsIntArray[j]) { // 3.1)
                
                while (i >= 0) {
                    numberAsIntArray[j] = numberAsIntArray[i];
                    i--;
                    j++;
                }
                for (int k = 0; k < numberAsIntArray.length; k++)
                    System.out.print(numberAsIntArray[k]);
                System.out.println();
            } else { // 3.2 like case 2
                if (length % 2 == 0) {
                    i = mid - 1;
                    j = mid;
                } else {
                    i = mid;
                    j = i;
                }
                addOneToMiddleWithCarry(numberAsIntArray, i, j, false);
            }
        }
    }

    private static void whenAll9(int length) {
        
        for (int i = 0; i <= length; i++) {
            if (i == 0 || i == length)
                System.out.print('1');
            else
                System.out.print('0');
        }
    }

    private static void addOneToMiddleWithCarry(int[] numberAsIntArray, int i,
            int j, boolean palindrom) {
        numberAsIntArray[i]++;
        numberAsIntArray[j] = numberAsIntArray[i];
        while (numberAsIntArray[i] == 10) {
            numberAsIntArray[i] = 0;
            numberAsIntArray[j] = numberAsIntArray[i];
            i--;
            j++;
            numberAsIntArray[i]++;
            numberAsIntArray[j] = numberAsIntArray[i];
        }
        
        if (!palindrom)
            while (i >= 0) {
                numberAsIntArray[j] = numberAsIntArray[i];
                i--;
                j++;
            }
        
        for (int k = 0; k < numberAsIntArray.length; k++)
            System.out.print(numberAsIntArray[k]);
        System.out.println();
    }

}
person uberchilly    schedule 30.03.2014
comment
Бьюсь об заклад, есть способ сделать этот код намного короче и проверяемым модульными тестами. - person Roland Illig; 30.08.2019

Попробуй это

public static String genNextPalin(String base){
    //check if it is 1 digit
    if(base.length()==1){
        if(Integer.parseInt(base)==9)
            return "11";
        else
            return (Integer.parseInt(base)+1)+"";
    }
    boolean check = true;
    //check if it is all 9s
    for(char a: base.toCharArray()){
        if(a!='9')
            check = false;
    }
    if(check){
        String num = "1";
        for(int i=0; i<base.length()-1; i++)
            num+="0";
        num+="1";
        return num;
    }

    boolean isBasePalin = isPalindrome(base);
    int mid = base.length()/2;
    if(isBasePalin){
        //if base is palin and it is odd increase mid and return
        if(base.length()%2==1){
            BigInteger leftHalf = new BigInteger(base.substring(0,mid+1));
            String newLeftHalf = leftHalf.add(BigInteger.ONE).toString();
            String newPalin = genPalin2(newLeftHalf.substring(0,mid),newLeftHalf.charAt(mid));
            return newPalin;
        }
        else{
            BigInteger leftHalf = new BigInteger(base.substring(0,mid));
            String newLeftHalf = leftHalf.add(BigInteger.ONE).toString();
            String newPalin = genPalin(newLeftHalf.substring(0,mid));
            return newPalin;
        }
    }
    else{
        if(base.length()%2==1){
            BigInteger leftHalf = new BigInteger(base.substring(0,mid));
            BigInteger rightHalf = new BigInteger(reverse(base.substring(mid+1,base.length())));

            //check if leftHalf is greater than right half
            if(leftHalf.compareTo(rightHalf)==1){
                String newPalin = genPalin2(base.substring(0,mid),base.charAt(mid));
                return newPalin;
            }
            else{
                BigInteger leftHalfMid = new BigInteger(base.substring(0,mid+1));
                String newLeftHalfMid = leftHalfMid.add(BigInteger.ONE).toString();
                String newPalin = genPalin2(newLeftHalfMid.substring(0,mid),newLeftHalfMid.charAt(mid));
                return newPalin;
            }
        }
        else{
            BigInteger leftHalf = new BigInteger(base.substring(0,mid));
            BigInteger rightHalf = new BigInteger(reverse(base.substring(mid,base.length())));

            //check if leftHalf is greater than right half
            if(leftHalf.compareTo(rightHalf)==1){
                return genPalin(base.substring(0,mid));
            }
            else{
                BigInteger leftHalfMid = new BigInteger(base.substring(0,mid));
                String newLeftHalfMid = leftHalfMid.add(BigInteger.ONE).toString(); 
                return genPalin(newLeftHalfMid);
            }
        }
    }
}

public static String genPalin(String base){
    return base + new StringBuffer(base).reverse().toString();
}
public static String genPalin2(String base, char middle){
    return base + middle +new StringBuffer(base).reverse().toString();
}

public static String reverse(String in){
    return new StringBuffer(in).reverse().toString();
}

static boolean isPalindrome(String str) {    
    int n = str.length();
    for( int i = 0; i < n/2; i++ )
        if (str.charAt(i) != str.charAt(n-i-1)) 
            return false;
    return true;    
}
person Eric Kim    schedule 13.04.2013
comment
Это действительно сложный код. Определенно можно написать это более элегантно. - person Roland Illig; 30.08.2019

Мы можем легко найти следующий палиндром, как показано ниже.

private void findNextPalindrom(int i) {
    i++;
    while (!checkPalindrom(i)) {
        i++;
    }
    Log.e(TAG, "findNextPalindrom:next palindrom is===" + i);
}


private boolean checkPalindrom(int num) {
    int temp = num;
    int rev = 0;
    while (num > 0) {
        int rem = num % 10;
        rev = rev * 10 + rem;
        num = num / 10;
    }
    return temp == rev;
}
person Tarun A    schedule 16.11.2020

HI Вот еще один простой алгоритм с использованием python,

  def is_palindrome(n):
      if len(n) <= 1:
          return False
      else:
          m = len(n)/2
          for i in range(m):
              j = i + 1
              if n[i] != n[-j]:
                  return False
          return True

  def next_palindrome(n):
      if not n:
          return False
      else:
          if is_palindrome(n) is True:
              return n
          else:
             return next_palindrome(str(int(n)+1))

  print next_palindrome('1000010')
person James    schedule 03.12.2013
comment
Это не эффективное решение. Также для проверки, является ли это палиндромом, мы можем использовать это: str(a) == ''.join(reversed(str(a))) - person coding_pleasures; 05.03.2015
comment
конечно, мы можем это сделать, но интервьюер не позволяет использовать встроенные функции. - person James; 05.03.2015

Я написал комментарии, чтобы прояснить, что делает каждый шаг в этом коде Python.

Одна вещь, которую необходимо принять во внимание, заключается в том, что входные данные могут быть очень большими, и мы не можем просто выполнять над ними целочисленные операции. Поэтому принимать ввод в виде строки, а затем манипулировать ею было бы намного проще.

tests = int(input())
results = []
for i in range(0, tests):
    pal = input().strip()
    palen = len(pal)
    mid = int(palen/2)
    if palen % 2 != 0:
        if mid == 0: # if the number is of single digit e.g. next palindrome for 5 is 6 
            ipal = int(pal)
            if ipal < 9:
                results.append(int(pal) + 1)
            else:
                results.append(11) # for 9 next palindrome will be 11
        else:
            pal = list(pal)
            pl = l = mid - 1
            pr = r = mid + 1
            flag = 'n' # represents left and right half of input string are same
            while pl >= 0:
                if pal[pl] > pal[pr]:
                    flag = 'r' # 123483489 in this case pal[pl] = 4 and pal[pr] = 3 so we just need to copy left half in right half
                    break      # 123484321 will be the answer
                elif pal[pl] < pal[pr]:
                    flag = 'm' # 123487489 in this case pal[pl] = 4 and pal[pr] = 9 so copying left half in right half will make number smaller
                    break # in this case we need to take left half increment by 1 and the copy in right half 123494321 will be the anwere
                else:
                    pl = pl -1
                    pr = pr + 1
            if flag == 'm' or flag == 'n': # increment left half by one and copy in right half
                if pal[mid] != '9': # if mid element is < 9 the we can simply increment the mid number only and copy left in right half
                        pal[mid] = str(int(pal[mid]) + 1)
                        while r < palen:
                            pal[r] = pal[l]
                            r = r + 1
                            l = l - 1
                        results.append(''.join(pal))
                else: # if mid element is 9 this will effect entire left half because of carry
                    pal[mid] = '0' # we need to take care of large inputs so we can not just directly add 1 in left half
                    pl = l
                    while pal[l] == '9':
                        pal[l] = '0'
                        l = l - 1
                    if l >= 0:
                        pal[l] = str(int(pal[l]) + 1)
                    while r < palen:
                        pal[r] = pal[pl]
                        r = r + 1
                        pl = pl - 1
                    if l < 0:
                        pal[0] = '1'
                        pal[palen - 1] = '01'
                    results.append(''.join(pal))
            else:
                while r < palen: # when flag is 'r'
                    pal[r] = pal[l]
                    r = r + 1
                    l = l - 1
                results.append(''.join(pal))
    else: # even length almost similar concept here with flags having similar significance as in case of odd length input
        pal = list(pal)
        pr = r = mid
        pl = l = mid - 1
        flag = 'n'
        while pl >= 0:
            if pal[pl] > pal[pr]:
                flag = 'r'
                break
            elif pal[pl] < pal[pr]:
                flag = 'm'
                break
            else:
                pl = pl -1
                pr = pr + 1
        if flag == 'r':
            while r < palen:
                    pal[r] = pal[l]
                    r = r + 1
                    l = l - 1
            results.append(''.join(pal))
        else:
            if pal[l] != '9':
                pal[l] = str(int(pal[l]) + 1)
                while r < palen:
                    pal[r] = pal[l]
                    r = r + 1
                    l = l - 1
                results.append(''.join(pal))
            else:
                pal[mid] = '0'
                pl = l
                while pal[l] == '9':
                    pal[l] = '0'
                    l = l - 1
                if l >= 0:
                    pal[l] = str(int(pal[l]) + 1)
                while r < palen:
                    pal[r] = pal[pl]
                    r = r + 1
                    pl = pl - 1
                if l < 0:
                    pal[0] = '1'
                    pal[palen - 1] = '01'
                results.append(''.join(pal))

for xx in results:
    print(xx) 
person quintin    schedule 30.10.2016
comment
Я предоставил комментарии в коде, чтобы прояснить ситуацию. Если есть какая-либо конкретная причина для голосования или если это не удается для какого-либо тестового примера, пожалуйста, прокомментируйте. - person quintin; 20.09.2017
comment
(1) ваш код намного длиннее, чем необходимо (2) он не определяет правильно названную функцию для выражения абстракции (3) xx — неправильное имя переменной, поскольку оно не несет никакой информации читателю (4) в коде нет абзацев, чтобы дать читателю возможность прервать чтение и перевести дух (5) в качестве флага используются магические значения n, r, m; флаг обычно имеет логический тип (6), совершенно неясно, что содержит results, поскольку он печатается в цикле, тогда как nextPalindrome должен явно возвращать одну строку или число. - person Roland Illig; 02.12.2018

Простые коды и тестовый вывод:

class NextPalin
{
public static void main( String[] args )
{
    try {
        int[] a = {2, 23, 88, 234, 432, 464, 7887, 7657, 34567, 99874, 7779222, 2569981, 3346990, 229999, 2299999 };
        for( int i=0; i<a.length; i++)
        {
            int add = findNextPalin(a[i]);
            System.out.println( a[i] + "  +  "  + add +  "  = "  + (a[i]+add)  );
        }
    }
    catch( Exception e ){}
}

static int findNextPalin( int a ) throws Exception
{
    if( a < 0 ) throw new Exception();
    if( a < 10 ) return a;

    int count = 0, reverse = 0, temp = a;
    while( temp > 0 ){
        reverse = reverse*10 + temp%10;
        count++;
        temp /= 10;
    }

    //compare 'half' value
    int halfcount = count/2;
    int base = (int)Math.pow(10, halfcount );
    int reverseHalfValue = reverse % base;
    int currentHalfValue = a % base;

    if( reverseHalfValue == currentHalfValue ) return 0;
    if( reverseHalfValue > currentHalfValue )  return  (reverseHalfValue - currentHalfValue);

    if(  (((a-currentHalfValue)/base)%10) == 9 ){
        //cases like 12945 or 1995
        int newValue = a-currentHalfValue + base*10;
        int diff = findNextPalin(newValue);
        return base*10 - currentHalfValue + diff;
    }
    else{
        return (base - currentHalfValue + reverseHalfValue );
    }
}
}

$ java NextPalin
2  +  2  = 4
23  +  9  = 32
88  +  0  = 88
234  +  8  = 242
432  +  2  = 434
464  +  0  = 464
7887  +  0  = 7887
7657  +  10  = 7667
34567  +  76  = 34643
99874  +  25  = 99899
7779222  +  555  = 7779777
2569981  +  9771  = 2579752
3346990  +  443  = 3347433
229999  +  9933  = 239932
2299999  +  9033  = 2309032
person user2495698    schedule 18.06.2013
comment
(1) Дамп кода не является ответом. Возможно, объясните, что вы сделали, как это работает и т. д. (2) Вы видели ту часть о числе, имеющем до миллиона цифр, верно? Ints не сработает... ни в коем случае. - person cHao; 18.06.2013

person    schedule
comment
это ужасный ответ. - person Mox; 20.01.2017
comment
@Mox, ты должен хотя бы сказать, почему этот ответ ужасен. Это ужасно, потому что (1) он работает только для чисел до 11 цифр (2) он использует поля, в которых локальные переменные более подходят (3) temp никогда не является подходящим именем для поля; максимальная допустимая область действия для переменной с таким именем — это блок примерно из 3 строк, при использовании в операции swap (4) алгоритму требуется очень много времени для вычисления следующего 10-значного палиндрома (5) имя NextPalindrome не подходит к классу, это подходит для метода, хотя (6) метод printNextPalindrome ничего не печатает - person Roland Illig; 02.12.2018
comment
@RolandIllig спасибо за ваш отзыв. этому комментарию почти 2 года. - person Mox; 02.12.2018