[2014亞馬遜amazon] 在線筆試題 大於非負整數N的第一個回文數 Symmetric Number


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 }
View Code

通過代碼中的驗證程序,可以驗證算法的正確性,呵呵,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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM