[Leetcode] 273. Integer to English Words

这一题真的只是烦而已。。。

这题的关键就是要看出英语算数字是每三个数一组的。
譬如说这个数:1,234,567。就是1 million 234 thousand 567这样。
再往下细谈,就是 "one" million "two hundred thirty four" thousand "five hundred sixty seven" 
又或者说:1,234,567,890。就是1 billion 234 million 567 thousand 890
往下细谈, 就是 "one" billion "two hundred thirty four" million "five hundred sixty seven" thousand "eight hundred ninety"
然后呢,每一组三个数字,每一位就需要分开处理。譬如,234,就是200 + 30 + 4 就是 two hundred + thirty + four。
当然,十位数和个位数的组合也是有特例的,就是11 ~ 19和0, 其中0是不需要翻译的,也就是200是不需要翻译成 two hundred + zero + zero的,一个two hundred就完事了。至于11到19,是特别的字符串,eleven啊,twelve啊,thirteen啊。。而不是10 + 3 = ten + three这个样子,所以也要特别处理。

所以做法其实很简单,我们就要有几个mapping。第一个是0 到 19 的mapping,用来应付十位数和个位数为0 ~ 19的特别情况。第二个是20, 30, ... 90的mapping,这个就是20 ~ 90 在十位数上的名称mapping。 第三个就是1000, 1000000, 1,000,000,000的mapping,就是每三个一组的mapping,因为input是保证在整型数的范围的,所以最大不会超过billion的级别。

有了这些mapping之后就很简单了,每次求模1000,得到0 ~ 999的范围,然后进行分析,百位数有的话就有,否则直接略过。然后0 ~ 99的范围也根据上面表述的进行翻译。一个特殊情况就是如果这一组是0的话,就直接跳过thousand million或者billion,也就是表示这一组不输出任何字符串。举个例子,1000000就是one million,你不会说one million zero thousand zero这样。但是,还有一个最终特例,那就是0,遇到0就直接输出Zero,上面那套是不管用的。根据上面的描述,可以得到代码如下:

    public String numberToWords(int num) {
        if (num == 0) return "Zero";

        String[] numStrMap = {
            "Zero",
            "One",
            "Two",
            "Three",
            "Four",
            "Five", 
            "Six",
            "Seven",
            "Eight",
            "Nine",
            "Ten",
            "Eleven",
            "Twelve",
            "Thirteen",
            "Fourteen",
            "Fifteen",
            "Sixteen",
            "Seventeen",
            "Eighteen",
            "Nineteen"
        };
        
        String[] tenStrMap = {
            "",
            "Twenty",
            "Thirty",
            "Forty",
            "Fifty",
            "Sixty",
            "Seventy",
            "Eighty",
            "Ninety"
        };        
        
        String[] quarMap = {
            "",
            "Thousand",
            "Million",
            "Billion"
        };
        
        Stack<String> strStk = new Stack<>();
        StringBuilder builder = new StringBuilder();
        int quarNum = 0;
        while (num > 0) {
            int curPart = num % 1000;
            if (curPart > 0) {
                strStk.push(quarMap[quarNum]);

                int tenPart = curPart % 100;
                if (tenPart > 0) {
                    if (tenPart < 20) {
                        strStk.push(numStrMap[tenPart]);
                    } else {
                        int single = tenPart % 10;
                        if (single > 0) {
                            strStk.push(numStrMap[single]);
                        }
                        strStk.push(tenStrMap[tenPart / 10 - 1]);
                    }
                }

                if (curPart >= 100) {
                    strStk.push("Hundred");
                    strStk.push(numStrMap[curPart / 100]);
                }
            }
            num /= 1000;
            quarNum++;
        }
        
        while (!strStk.isEmpty()) {
            builder.append(strStk.pop());
            if (!strStk.isEmpty() && !strStk.peek().equals("")) {
                builder.append(' ');
            }
        }
        
        return builder.toString();
    }

看得出来这题就是烦,case分支很多,special cases也有几个。那几个mapping特别长。真正算法部分的代码大约就是30多行。

猜你喜欢

转载自blog.csdn.net/chaochen1407/article/details/81907199