如果思考算法的解法方案是一种模拟,那么这一般不是个好的解决方案。对于一个复杂的问题,挖掘其中的规律,把问题抽象处理统一解决,这样代码才会简洁清晰。
将数字分解成三部分,亿 & 万 & 无单位,通过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[] {"", "万", "亿"};
}
同样采用抽象统一的思想,规律也很容易发现,每三个数分为一趴,单位分别为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 阿拉伯数转英文