[字符串 数学] 273. 整数转换英文表示(分组转换)

[字符串 数学] 273. 整数转换英文表示(分组转换)

273. 整数转换英文表示

题目链接:https://leetcode-cn.com/problems/integer-to-english-words/


分类:

  • 数学(给定数字转英文的规则、数字分组转换:从最低位开始每3位分成一组进行转换)
  • 字符串(设置字符串数组:THOUSAND,LESS_THAN_TWENTY,HUNDRED作为字典数组、转换细节:空格符的处理)

在这里插入图片描述

思路:分组转换

理解转换规则:
int型最大数是:2,147,483,647,共10位。
整个数字可以按逗号划分为多个部分,每个部分都按三位数进行英文转换:

例如 147:One Hundred Forty Seven,最后再在后面加上量级:One Hundred Forty Seven Million

三位数中含0时的转换:

例如 103:one hundred three,而不是one hundred and three

转换前所需要的准备:

为了转换方便,我们先将0~19,每个整十,三个量级都预先存放在数组中,作为字典数组供查询使用:

private final String[] THOUSAND = {"", "Thousand", "Million", "Billion"};
private final String[] LESS_THAN_TWENTY = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
private final String[] HUNDRED = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};

其中,LESS_THAN_TWENTY数组存放的是0~19对应的英语,且0对应的是空字符串"";
同理HUNDRED数组中0和10对应的英语也设置为空字符串,因为10对应的ten已经在
LESS_THAN_TWENTY中了。

转换的具体流程:

对整个数字我们可以分为多个部分来处理,例如:2,147,483,647 从最低位开始每3位数分为一组,可以分为4个分组,每个分组最多3位数字,分组的内部处理都是相同的,内部处理结束后返回对应的英文字符串,将这4个分组对应的英文字符串组合起来,就能得到最终的转换结果。

从整体上看,我们每次处理的分组就是num的最低3位(即 num % 1000),然后将num的int形式向右移动3位(即num / 1000),再处理当前num的最低3位,直到num == 0。

在最终转换结果res中,越先处理的3位数字得到的英文字符串在res中排在越后面:

例如:num = 2,147,483,647
最先处理num的低3位647(num % 1000),得到"Six Hundred Forty Seven",res="Six Hundred Forty Seven"
	num右移3位:num / 1000 = 2 147 483
接着处理num的低3位483,得到"Four Hundred Eighty Three Thousand",需要前插到res的首部,即res="Four Hundred Eighty Three Thousand Six Hundred Forty Seven"

...以此类推。

因此,我们需要使用StringBuilder的insert函数,将当前分组得到的英文字符串前插到res的0下标处:

	res.insert(0, str);//向res的首部插入str

分组内部处理helper函数:
先开辟一个StringBuilder来存放分组转换的英语字符串;

例如:2,147,483,647

最先处理的分组是num = 647,我们从百位到个位依次处理:

第一阶段:获取百位上的数值:647/100=6,因为可能存在047这种百位为0的情况,所以只有百位数值 > 0才对百位做进一步处理:

  • 将百位数值6转换成英语(通过LESS_THAN_TWENTY[6]获取),接着加上" Hundred "(注意Hundred前后的空格符不能省略);
  • 将647去除百位:num = 647 % 100 = 47,进入下一阶段;

第二阶段:处理此时的num:

  • 如果num >= 20,则模仿百位对十位做进一步处理:
    • 将num的十位数值4(num/10=4)转换成英语(通过HUNDRED[4]获取"Forty");
    • 将47去除十位:num = 47 % 10 = 7,进入第三阶段;
  • 如果num < 20,则直接进入第三阶段:

第三阶段:将此时的num=7转换成英语(通过LESS_THAN_TWENTY[7]获取);

最后,在生成的英语字符串末尾加上量级对应的英语:

  • 647对应的量级是0,字符串末尾不需要加任何量级,所以把THOUSAND[0]设置为空字符串"";
  • 484对应的量级是1,字符串末尾要加上"Thousand";
  • 147对应的量级是2,字符串末尾要加上"Million";
  • 2对应的量级是3,字符串末尾要加上"Billion"。

除了上述的主要流程,内部处理还有需要注意的细节:

  1. 如果需要转换的三位数全为0,则直接转换成空字符串,不需要将0转换成英语,也不需要加量级,

     例如:1000000 输出:"One Million",前两个000都只转换成空字符串。
    
  2. 百位的"Hundred"之后、十位的英语之后、个位的英语之后、量级的英语之后都记得加上空格符,但这样可能导致整个num转换成英语字符串时末尾可能有多余的空格符,所以在返回最终结果前将尾部的空格符去掉:trim()。

实现代码:

class Solution {
    private final String[] THOUSAND = {"", "Thousand", "Million", "Billion"};
    private final String[] LESS_THAN_TWENTY = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    private final String[] HUNDRED = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};

    public String numberToWords(int num) {
        //特殊用例
        if(num == 0) return "Zero";

        //level用于记录当前三位数所在的量级(level=1:"Thousand", =2:"Million", =3:"Billion")
        int level = 0;
        //res存放数字num转换的英语字符串
        StringBuilder res = new StringBuilder();
        //每次处理num的低3位,然后将num右移3位,直到num==0
        while(num != 0){
            //获取当前num的低3位转换的英文字符串
            String part = helper(num % 1000, level);
            //将转换的英文前插到res首部(insert的使用是关键)
            res.insert(0, part);
            //每处理完3位数字,量级+1
            level++;
            //num的int型右移3位
            num /= 1000;
        }
        //最后返回前要去除首尾可能存在的空格符
        return res.toString().trim();
    }
    //对每部分(最多3位数字)做内部处理,返回该部分对应的英文,level表示num这三位数所在的量级
    public String helper(int num, int level){
        StringBuilder sb = new StringBuilder();
        //如果num为0,则直接返回空字符串
        if(num == 0) return sb.toString();
        //如果num的百位不为0,则做百位数值的转换
        if(num / 100 > 0) {
            sb.append(LESS_THAN_TWENTY[num / 100]).append(" Hundred ");
            num %= 100;
        }
        //如果此时num >= 20,则对十位数值做转换,然后提取num的个位数
        if(num >= 20){
            sb.append(HUNDRED[num / 10]).append(" ");
            num %= 10;//获取num的个位数
        }
        //如果此时num < 20,则直接做英文转换
        if(num > 0){
            sb.append(LESS_THAN_TWENTY[num]).append(" ");
        }
        //最后在英文字符串末尾加上当前num所在的量级的英文
        sb.append(THOUSAND[level]).append(" ");
        return sb.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值