阿拉伯数转中文与英文[找到规律,抽象问题,转换成代码]

前言

如果思考算法的解法方案是一种模拟,那么这一般不是个好的解决方案。对于一个复杂的问题,挖掘其中的规律,把问题抽象处理统一解决,这样代码才会简洁清晰。

一、阿拉伯数字转换

1、阿拉伯数字转中文

a、案例

在这里插入图片描述

b、解决方案

将数字分解成三部分,亿 & 万 & 无单位,通过for循环分片出来即可,三部分处理方式是一样的,唯一不同的就是最后的单位添加。
而对于每一部分,具体的处理方式一样,分成个十百千四个级别,所有用一个函数统一处理即可。
注:需要注意到细节,
1.只有一种前导为零的情况要特殊处理;
2.每部分末尾不能为0
3.多个零只能写一个
4.有零的时候表不表达出来要根据前面是否为0

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型
     * @return string字符串
     */
    public String num2cn (int n) {
        // 唯一一个前导可以为零!
        if (n == 0) return "零";
        // 统一为正数处理。
        boolean isNeg = n < 0;
        n = Math.abs(n);
        // 把规律抽象出来,
        // 将这个数字分成三部分,亿 & 万 & 无单位
        // 每一部分,末尾是不能以0结尾的;多个零只能用一个零表示。
        StringBuilder sb = new StringBuilder();
        for (int i = 2, unit = (int)1e8; i >= 0; i--, unit /= 1e4) {
            int part = n / unit;
            if (part != 0) {
                sb.append(toChinese(part)).append(units[i]);
                n %= unit;
            }
        }
        
        String rs = sb.toString();
        // 特殊情况,一十开头变成十。
        if ("一十".equals(rs.substring(0, 2))) rs = rs.substring(1);
        // 前缀是否为负,要加上。
        if (isNeg) rs = "负" + rs;
        return rs;
    }
    boolean preIsZero = true;// 只要前面有非零数,那么零就需要表达出来。
    public String toChinese(int num) {
        StringBuilder sb = new StringBuilder();
        // 分成四个部分处理,千 & 百 & 十 & 个位
        for (int i = 3, unit = (int)1e3; i >= 0; i--, unit /= 10) {
            int cur = num / unit;

            if (cur != 0) {
                sb.append(chinese[cur]).append(base[i]);
                preIsZero = false;
            } else if (!preIsZero) {
                sb.append(chinese[cur]);
                preIsZero = true;
            }
            num %= unit;
        }
        // 每一部分,都不能以零结尾。
        if ("零".equals(sb.substring(sb.length() - 1))) {
            // 如果为零,还得更改preIsZero,设置为false,毕竟把零给去了。
            preIsZero = false;
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    static String[] chinese =
        new String[] {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
    static String[] base = new String[] {"", "十", "百", "千"};
    static String[] units = new String[] {"", "万", "亿"};
}

2、阿拉伯数转英文

a、案例

在这里插入图片描述

b、解决方案

同样采用抽象统一的思想,规律也很容易发现,每三个数分为一趴,单位分别为Billion Million Thousand 无单位。
注:和中文不同的时,十几和其他两位数的处理方式。

class Solution {
    // num的范围从0-20亿。
    // 数字转英文,不同于中文,
    // 右到左每三位一组划分,Millon,Thousand,结尾,3位用一个函数获取转换后的结果,当作最低三位。
    public String numberToWords(int num) {
        if(num == 0) return "Zero";
        StringBuilder sb = new StringBuilder();
        for(int i = 3,unit = (int)1e9;i >= 0;i--,unit /= (int)1e3){
            int cur = num / unit;
            if(cur != 0){
                sb.append(toEnglish(cur)).append(thousands[i]).append(' ');
                num %= unit;
            }
        }
        return sb.toString().trim();
    }
    public String toEnglish(int num){
        StringBuilder sb = new StringBuilder();

        int i = num / 100;
        if(i != 0) sb.append(singles[i]).append(" Hundred ");
        num %= 100;
        i = num / 10;
        if(i > 1) {
            sb.append(tens[i]).append(' ');
            num %= 10;
        }
        if(num == 0) return sb.toString();
        if(num < 10) sb.append(singles[num]).append(' ');
        else sb.append(teens[num % 10]).append(' ');
        
        return sb.toString();
    }
    String[] singles = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
    String[] teens = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    String[] tens = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    String[] thousands = {"", "Thousand", "Million", "Billion"};
}

总结

1)模拟不是算法,算法需要抽象问题,让问题有统一简洁的处理方式,抓住规律才能让问题简单起来。
2)善用数据结构,善用空间存储,降低时间复杂度,比如常用的数组,是一个很好用的数组hash。

参考文献

[1] LeetCode 阿拉伯数转中文
[2] LeetCode 阿拉伯数转英文

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值