1.題目
如標題,求大於整數N(N>=0)的第一個回文數的字符串表示形式。
這個題目也是當時筆試第一次見到,花了一個小時才做出了。慢慢總結還是挺簡單的。
2.分析
分析如下:
(1)一位數N(9除外)。
第一個大於N回文數等於N+1,如大於3的第一個回文數是4。

(2)奇數位(一位數除外)
需要看“左邊反轉數字”是否大於"右邊數字"。
1)如果小於等於,則“左邊+中間字母”組成的數字+1,再對稱就可以。
2)如果大於,則左邊數字直接對稱到右邊就可以啦。

(3)偶數位
需要看“左邊反轉數字”是否大於"右邊數字"。
1)如果小於等於,則“左邊”組成的數字+1,再對稱就可以。
2)如果大於,則左邊數字直接對稱到右邊就可以啦。

(4)特殊情況(其實就一種)
1)N=9,大於N的下一個回文數是11,即N+2
2)奇數情況(位數!=1)。
N1=99900,右邊數字小於“左邊,翻轉數字”,直接對稱,所以大於N1的第一個回文數是99999。(滿足上面的討論規則)
N2=99999,右邊數組大於等於“左邊,翻轉數字”,使用上面的討論規則結果為1000 001 ,不正確。結果應該是N2+2
3)偶數情況。
N1=9900,右邊數字小於“左邊翻轉數字”,直接對稱,所以大於N1的第一個回文數是9999。(滿足上面的討論規則)
N2=9999,右邊數組大於等於“左邊翻轉數字”,使用上面的討論規則結果為100 001 ,不正確。結果應該是N2+2
所以,可以將特殊情況歸結為一種,當整數N滿足正則表達式"9+"時,大於N的第一個回文數是N+2。(9,99,999,9999,.....)
3.生成代碼+測試代碼
1 /** 2 * 生成函數: 3 * firstBiggerPalindrome(String n) 4 * isLeftReverseBiggerRight(String left, String right) 5 * 后期使用for循環校驗N in [0,1000000)時的情況函數: 6 * nextPalindromeUseFor(int num, boolean[] Palindrome) 7 * isPalindrome(int num) 8 * 9 * 在main函數內進行算法生成 與 for循環暴力生成的校驗 10 * */ 11 12 public class Solution { 13 static String firstBiggerPalindrome(String n) { // 生成大於整數N(字符串表示)的第一個回文整數 14 n = String.valueOf(Integer.parseInt(n)); // 避免前導符"0",如n="009" 15 if (n.matches("9+")) // 特殊情況直接處理 16 return String.valueOf(Integer.parseInt(n) + 2); 17 18 int len = n.length(); 19 if (len == 1) // 長度為1 20 return String.valueOf(Integer.parseInt(n) + 1); 21 StringBuilder left = new StringBuilder(); // 左邊 22 StringBuilder right = new StringBuilder(); // 右邊 23 StringBuilder res = new StringBuilder(); // 結果 24 if ((len & 0x1) == 1) { // 奇數位 25 left.append(n.substring(0, len >> 1)); 26 right.append(n.substring((len >> 1) + 1)); 27 if (isLeftReverseBiggerRight(left.toString(), right.toString())) { // 如果左邊翻轉數字大於右邊,直接翻轉 28 res.append(left); 29 res.append(n.charAt(len >> 1)); 30 res.append(left.reverse().toString()); 31 } else { // 否則,“左邊+中間”數字加1,再翻轉 32 left.append(n.charAt(len >> 1)); 33 int num = Integer.parseInt(left.toString()) + 1; 34 left.setLength(0); 35 left.append(num); 36 37 res.append(num); 38 res.append(left.deleteCharAt(left.length() - 1).reverse() 39 .toString()); 40 } 41 } else { // 偶數為 42 left.append(n.substring(0, len >> 1)); 43 right.append(n.substring(len >> 1)); 44 if (!isLeftReverseBiggerRight(left.toString(), right.toString())) { 45 int num = Integer.parseInt(left.toString()) + 1; 46 left.setLength(0); 47 left.append(num); 48 } 49 res.append(left.toString()); 50 res.append(left.reverse().toString()); 51 } 52 return res.toString(); 53 } 54 55 static boolean isLeftReverseBiggerRight(String left, String right) { // 比較左邊翻轉后數字與右邊數字的大小關系 56 StringBuilder sb = new StringBuilder(left); 57 if (sb.reverse().toString().compareTo(right) > 0) 58 return true; 59 return false; 60 } 61 62 static String nextPalindromeUseFor(int num, boolean[] Palindrome) { // 求大於num的第一個回文數(最后的測試代碼使用) 63 for (int i = num + 1; i < Palindrome.length; i++) { 64 if (Palindrome[i] == true) 65 return String.valueOf(i); 66 } 67 return null; 68 } 69 70 static boolean isPalindrome(int num) { // 判斷一個數字是不是回文數字(最后的測試代碼使用) 71 String str = String.valueOf(num); 72 int i = 0; 73 int j = str.length() - 1; 74 while (i < j) { 75 if (str.charAt(i) != str.charAt(j)) 76 return false; 77 i++; 78 j--; 79 } 80 return true; 81 } 82 83 public static void main(String[] args) throws IOException { 84 int n = 1000000; // 只測試[0,1000000)以內的結果 85 boolean[] Palindrome = new boolean[n]; //默認為false 86 for (int i = 0; i < n; i++) { 87 if (isPalindrome(i)) 88 Palindrome[i] = true; //如果是回文數字,標記為true。編譯下一步校驗,大於N的第一個回文數字 89 } 90 91 for (int i = 0; i < n; i++) { 92 String val = firstBiggerPalindrome(String.valueOf(i)); //程序生成 93 if (Integer.parseInt(val) < n) { //如果在[0,1000000)內,進行校驗 94 if (!val.equals(nextPalindromeUseFor(i, Palindrome))) 95 System.out.println("BAD\t" + i); 96 } 97 } 98 } 99 }
通過代碼中的驗證程序,可以驗證算法的正確性,呵呵,nice!!!
Java編程小細節:
這個題目是字符串處理的,所以用了StringBuilder的reverse();注意一下
1 import java.io.*; 2 3 public class Solution { 4 public static void main(String[] args) throws IOException { 5 StringBuilder sb = new StringBuilder(); 6 sb.append("liuliuliu"); 7 System.out.println(sb.toString()); 8 sb.reverse(); //不需要返回值,也能翻轉,記住啊!!! 9 System.out.println(sb.toString()); 10 } 11 }
