17

まずここに問題があります:

正の整数は、左から右に読んでも右から左に読んでも、10 進法での表現が同じ場合、回文と呼ばれます。1000000 桁以下の正の整数 K に対して、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] 反復でオフセットを確実にインクリメントできると考えました。私のチャンクの確認または提案をいただければ幸いです。また、質問をより明確にする必要があるかどうかもお知らせください。

4

10 に答える 10

14

さて、私は一定の順序の解決策を持っています(少なくとも次数k、kは数字の桁数です)

n=17208 と仮定していくつかの例を見てみましょう

数値を真ん中から 2 つの部分に分割し、最も重要な部分をより重要でない部分に可逆的に書き込みます。つまり、17271 そのように生成された数値がnより大きい場合、それはあなたの回文です。中心の数値 (ピボット) を増やすだけではない場合、つまり、17371 が得られます。

他の例

n=17286 palidrome-attempt=17271 (ピボットをインクリメントする n より小さいため、この場合は 2) したがって palidrome=17371

n=5684 回文1=5665 回文=5775

n=458322 回文=458854

ここで、n = 1219901 palidrome1=1219121 と仮定します。ピボットをインクリメントすると、ここで私の番号が小さくなるので、ピボットに隣接する番号も 1220221 とインクリメントします

このロジックは拡張できます

于 2011-11-18T19:10:05.530 に答える
1
public class NextPalindrome 
{   
    int rev, temp;
    int printNextPalindrome(int n) 
    {
        int num = n;
        for (int i = num+1; i >= num; i++) 
        {
            temp = i;
            rev = 0;
            while (temp != 0) 
            {
                int remainder = temp % 10;
                rev = rev * 10 + remainder;
                temp = temp / 10;
            }
            if (rev == i) 
            {
                break;
            }
        }
        return rev;
    }
    public static void main(String args[]) 
    {
        NextPalindrome np = new NextPalindrome();
        int nxtpalin = np.printNextPalindrome(11);
        System.out.println(nxtpalin);
    }



}
于 2015-01-21T09:45:06.160 に答える
1

これが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();
    }

}
于 2014-03-30T15:38:47.627 に答える
0

これを試して

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;    
}
于 2013-04-13T04:40:11.233 に答える
-1

この Python コードで各ステップが何を行っているかを明確にするために、コメントを書きました。

考慮する必要があることの 1 つは、入力が非常に大きくなる可能性があるため、単純に整数演算を実行できないことです。したがって、入力を文字列として取得して操作する方がはるかに簡単です。

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) 
于 2016-10-30T12:59:55.727 に答える
-1

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')
于 2013-12-03T17:06:48.687 に答える
-2

簡単なコードとテスト出力:

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
于 2013-06-18T04:23:52.037 に答える