发布于 2014-10-10 05:56:52 | 790 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的精品教程,程序狗速度看过来!

亚马逊(Amazon)

亚马逊公司(Amazon,简称亚马逊;NASDAQ:AMZN),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图。是网络上最早开始经营电子商务的公司之一,亚马逊成立于1995年,一开始只经营网络的书籍销售业务,现在则扩及了范围相当广的其他产品,已成为全球商品品种最多的网上零售商和全球第二大互联网企业,在公司名下,也包括了AlexaInternet、a9、lab126、和互联网电影数据库(Internet Movie Database,IMDB)等子公司。


1.题目

  求大于整数N(N>=0)的第一个回文数的字符串表示形式。

  这个题目也是当时笔试第一次见到,花了一个小时才做出了。慢慢总结还是挺简单的。

什么是回文数:

"回文数"是一种数字。如:98789, 这个数字正读是98789,倒读也是98789,正读倒读一样,所以这个数字就是回文数。比如在自然数中,最小的回文数是0,其次是1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,101,111,121,131.....

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.生成代码+测试代码

/**
 * 生成函数:
 *         firstBiggerPalindrome(String n)
 *         isLeftReverseBiggerRight(String left, String right)
 * 后期使用for循环校验N in [0,1000000)时的情况函数:
 *         nextPalindromeUseFor(int num, boolean[] Palindrome)
 *         isPalindrome(int num)
 *
 * 在main函数内进行算法生成 与 for循环暴力生成的校验
 * */

public class Solution {
    static String firstBiggerPalindrome(String n) { // 生成大于整数N(字符串表示)的第一个回文整数
        n = String.valueOf(Integer.parseInt(n)); // 避免前导符"0",如n="009"
        if (n.matches("9+")) // 特殊情况直接处理
            return String.valueOf(Integer.parseInt(n) + 2);

        int len = n.length();
        if (len == 1) // 长度为1
            return String.valueOf(Integer.parseInt(n) + 1);
        StringBuilder left = new StringBuilder(); // 左边
        StringBuilder right = new StringBuilder(); // 右边
        StringBuilder res = new StringBuilder(); // 结果
        if ((len & 0x1) == 1) { // 奇数位
            left.append(n.substring(0, len >> 1));
            right.append(n.substring((len >> 1) + 1));
            if (isLeftReverseBiggerRight(left.toString(), right.toString())) { // 如果左边翻转数字大于右边,直接翻转
                res.append(left);
                res.append(n.charAt(len >> 1));
                res.append(left.reverse().toString());
            } else { // 否则,“左边+中间”数字加1,再翻转
                left.append(n.charAt(len >> 1));
                int num = Integer.parseInt(left.toString()) + 1;
                left.setLength(0);
                left.append(num);

                res.append(num);
                res.append(left.deleteCharAt(left.length() - 1).reverse()
                        .toString());
            }
        } else { // 偶数为
            left.append(n.substring(0, len >> 1));
            right.append(n.substring(len >> 1));
            if (!isLeftReverseBiggerRight(left.toString(), right.toString())) {
                int num = Integer.parseInt(left.toString()) + 1;
                left.setLength(0);
                left.append(num);
            }
            res.append(left.toString());
            res.append(left.reverse().toString());
        }
        return res.toString();
    }

    static boolean isLeftReverseBiggerRight(String left, String right) { // 比较左边翻转后数字与右边数字的大小关系
        StringBuilder sb = new StringBuilder(left);
        if (sb.reverse().toString().compareTo(right) > 0)
            return true;
        return false;
    }

    static String nextPalindromeUseFor(int num, boolean[] Palindrome) { // 求大于num的第一个回文数(最后的测试代码使用)
        for (int i = num + 1; i < Palindrome.length; i++) {
            if (Palindrome[i] == true)
                return String.valueOf(i);
        }
        return null;
    }

    static boolean isPalindrome(int num) { // 判断一个数字是不是回文数字(最后的测试代码使用)
        String str = String.valueOf(num);
        int i = 0;
        int j = str.length() - 1;
        while (i < j) {
            if (str.charAt(i) != str.charAt(j))
                return false;
            i++;
            j--;
        }
        return true;
    }

    public static void main(String[] args) throws IOException {
        int n = 1000000; // 只测试[0,1000000)以内的结果
        boolean[] Palindrome = new boolean[n];    //默认为false
        for (int i = 0; i < n; i++) {
            if (isPalindrome(i))
                Palindrome[i] = true;    //如果是回文数字,标记为true。编译下一步校验,大于N的第一个回文数字
        }

        for (int i = 0; i < n; i++) {
            String val = firstBiggerPalindrome(String.valueOf(i));    //程序生成
            if (Integer.parseInt(val) < n) {    //如果在[0,1000000)内,进行校验
                if (!val.equals(nextPalindromeUseFor(i, Palindrome)))
                    System.out.println("BAD\t" + i);
            }
        }
    }
}

通过代码中的验证程序,可以验证算法的正确性,呵呵,nice!!!

 

Java编程小细节:

这个题目是字符串处理的,所以用了StringBuilder的reverse();注意一下

import java.io.*;

public class Solution {
    public static void main(String[] args) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("liuliuliu");
        System.out.println(sb.toString());
        sb.reverse();    //不需要返回值,也能翻转,记住啊!!!
        System.out.println(sb.toString());
    }
}


 


最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务