まず、ここに問題があります:
正の整数は、左から右および右から左に読み取ったときに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]反復でオフセットを確実にインクリメントできると思いました。私の変更の確認または提案をいただければ幸いです。また、質問を明確にする必要があるかどうかもお知らせください。
これはたくさんのコードのようです。非常に素朴なアプローチをもう試しましたか?何かが回文であるかどうかを確認することは、実際には非常に簡単です。
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. 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
これは、説明したアルゴリズムに少し似ているように見えますが、内側の数字から始まり、外側に移動します。
さて、私は一定の次数の解を持っています(少なくとも次数k、ここでkは数の桁数です)
N = 17208と仮定していくつかの例を見てみましょう
数値を中央から2つの部分に分割し、重要度の高い部分を重要度の低い部分に可逆的に書き込みます。つまり、そのように生成された数があなたのnより大きい場合は17271、それはあなたの回文です。中心数(ピボット)を増やすだけではない場合、つまり、17371を取得します
他の例
n = 17286 palidrome-attempt = 17271(n未満であるため、ピボットをインクリメントします。この場合は2)、palidrome = 17371
n = 5684回文1 = 5665回文= 5775
n = 458322回文= 458854
ここで、n = 1219901 palidrome1 = 1219121ピボットをインクリメントすると、ここで私の番号が小さくなると仮定します。したがって、ピボットに隣接する番号もインクリメントします。1220221
このロジックは拡張できます
必要な操作が1つの単純な追加だけである場合、個々の数字をいじる理由はありません。次のコードは Raksの回答 に基づいています。
このコードは、意図的に実行速度よりも単純さを強調しています。
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"));
}
}
次のコードは、番号の次のPalandrome番号を検索します-
public class TestNextPalindrome {
public static void main(String[] args) {
int number1 = 45312;
int number2 = 12345;
int number3 = 12945;
int number4 = 4531;
int number5 = 1459;
int number6 = 1997;
System.out.print("For the number " + number1);
getNextPalindrome(number1);
System.out.print("For the number " + number2);
getNextPalindrome(number2);
System.out.print("For the number " + number3);
getNextPalindrome(number3);
System.out.print("For the number " + number4);
getNextPalindrome(number4);
System.out.print("For the number " + number5);
getNextPalindrome(number5);
System.out.print("For the number " + number6);
getNextPalindrome(number6);
}
private static void getNextPalindrome(int number) {
if (isSizeEven(number)) {
getNextPalindromeForEvenLengthNumbers(number);
}
else {
getNextPalindromeForOddLengthNumbers(number);
}
}
private static boolean isSizeEven(int number) {
if (String.valueOf(number).length() % 2 == 0)
return true;
return false;
}
private static void getNextPalindromeForEvenLengthNumbers(int number) {
StringBuilder testPalindromeString = new StringBuilder();
testPalindromeString.append(number);
StringBuilder convertTopalindrome = new StringBuilder();
convertTopalindrome.append(testPalindromeString.substring(0, testPalindromeString.length() / 2));
convertTopalindrome.append(testPalindromeString.delete(testPalindromeString.length() / 2,
testPalindromeString.length()).reverse());
//if the palindrome is greater than the original number
if (Integer.parseInt(convertTopalindrome.toString()) > number) {
System.out.println(" the next palindrome is " + convertTopalindrome);
}
else {
//get the middle elements in case of even numbers
String middleElements =
convertTopalindrome.substring(convertTopalindrome.length() / 2 - 1,
convertTopalindrome.length() / 2 + 1);
int middleElementsInt = Integer.valueOf(middleElements);
//we are going to increment the middle elements by 1 so check if after this the value is not greater than 99.
if (middleElementsInt + 11 < 99) {
convertTopalindrome.replace(convertTopalindrome.length() / 2 - 1,
convertTopalindrome.length() / 2 + 1, String.valueOf(middleElementsInt + 11));
System.out.println(" the next palindrome is " + convertTopalindrome);
}
else {
String numberTillMiddleElement =
convertTopalindrome.substring(0, convertTopalindrome.length() / 2 + 1);
int numberTillMiddleElementInt = Integer.valueOf(numberTillMiddleElement);
convertTopalindrome.replace(0, convertTopalindrome.length() / 2 + 1,
String.valueOf(numberTillMiddleElementInt + 1));
getNextPalindrome(Integer.valueOf(convertTopalindrome.toString()));
}
}
}
private static void getNextPalindromeForOddLengthNumbers(int number) {
StringBuilder testPalindromeString = new StringBuilder();
testPalindromeString.append(number);
StringBuilder convertTopalindrome = new StringBuilder();
convertTopalindrome.append(testPalindromeString.substring(0, testPalindromeString.length() / 2 + 1));
convertTopalindrome.append(testPalindromeString.delete(testPalindromeString.length() / 2,
testPalindromeString.length()).reverse());
//if the palindrome is greater than the original number
if (Integer.parseInt(convertTopalindrome.toString()) > number) {
System.out.println(" the next palindrome is " + convertTopalindrome);
}
else {
char middleElement = convertTopalindrome.charAt(convertTopalindrome.length() / 2);
int middleElementInt = Character.getNumericValue(middleElement);
//we are going to increment the middle element by 1 so check if after this the value is not greater than 9.
if (middleElementInt < 9) {
convertTopalindrome.replace(convertTopalindrome.length() / 2,
convertTopalindrome.length() / 2 + 1, String.valueOf(middleElementInt + 1));
System.out.println(" the next palindrome is " + convertTopalindrome);
}
else {
String numberTillMiddleElement =
convertTopalindrome.substring(0, convertTopalindrome.length() / 2 + 1);
int numberTillMiddleElementInt = Integer.valueOf(numberTillMiddleElement);
convertTopalindrome.replace(0, convertTopalindrome.length() / 2 + 1,
String.valueOf(numberTillMiddleElementInt + 1));
getNextPalindrome(Integer.valueOf(convertTopalindrome.toString()));
}
}
}
}
コードの説明はここにあります- Javaを使用して次の回文を見つける
これがJavaでの私のコードです。全体のアイデアはここからです http://www.geeksforgeeks.org/given-a-number-find-next-smallest-palindrome-larger-than-this-number/
java.util.Scannerをインポートします。
パブリッククラスメイン{
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();
}
}
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);
}
}
これを試して
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;
}