← 返回题目列表

如何把整数转换成英文单词?(LeetCode 273)

高频 困难 第 15 / 27 题 更新于 2026/07/30
数学与数论数位拆分递归字符串构造

简化版

整数转英文单词的核心是按三位一组拆分:BillionMillionThousand、最后一组。每组数字范围是 0 到 999,可以写一个 helper(num) 转成英文:小于 20 查表,小于 100 用十位表加个位,100 到 999 用 X Hundred 加余数。最后按大单位从高到低拼接,跳过值为 0 的组。

例如 1234567 拆成 1 Million234 Thousand567,结果是 One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven

详细版

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

    public String numberToWords(int num) {
        if (num == 0) return "Zero";
        int[] values = {1000000000, 1000000, 1000, 1};
        String[] units = {"Billion", "Million", "Thousand", ""};
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            if (num >= values[i]) {
                int part = num / values[i];
                num %= values[i];
                sb.append(helper(part)).append(units[i].isEmpty() ? "" : " " + units[i]).append(" ");
            }
        }
        return sb.toString().trim();
    }

    private String helper(int num) {
        if (num == 0) return "";
        if (num < 20) return below20[num];
        if (num < 100) return (tens[num / 10] + " " + helper(num % 10)).trim();
        return (below20[num / 100] + " Hundred " + helper(num % 100)).trim();
    }
}

重点是把大问题拆成“每三位一组”和“0 到 999 的小转换”。字符串拼接后要处理多余空格。

完整版教学

一、为什么按三位分组

英文数字的大单位是每三位一级:Thousand=10^3Million=10^6Billion=10^9。因此整数可以按三位一组拆开,每组内部用同一套 0 到 999 的规则转换。

1,234,567
1       -> One Million
234     -> Two Hundred Thirty Four Thousand
567     -> Five Hundred Sixty Seven

这样不用为每个数位写大量分支,逻辑会非常稳定。

二、0 到 999 的转换规则

helper(num) 只负责转换 1..999

  • 1..19:英文有特殊单词,直接查表。
  • 20..99:十位查表,再递归处理个位。
  • 100..999:百位查表,加 Hundred,再递归处理余数。
567
5 Hundred + helper(67)
67 = Sixty + helper(7)
7 = Seven
=> Five Hundred Sixty Seven

这个递归深度很小,最多拆百位、十位、个位。

三、大单位循环如何拼接

主函数按 Billion -> Million -> Thousand -> 个位组 处理:

int[] values = {1000000000, 1000000, 1000, 1};
String[] units = {"Billion", "Million", "Thousand", ""};

如果 num >= values[i],说明当前单位有非零组。先取 part = num / values[i],把这组三位以内的数字转英文,再追加单位名,最后 num %= values[i] 继续处理剩余部分。

四、为什么要跳过 0 组

英文数字不会读出中间的零组。例如 1000010One Million Ten,不是 One Million Zero Thousand Ten。因此只有当某个组的 part > 0 时才拼接。

数字分组正确输出
10001,000One Thousand
10000101,000,010One Million Ten
10000000011,000,000,001One Billion One

零组跳过是本题字符串正确性的关键。

五、空格处理是工程细节

递归拼接时很容易产生多余空格。常见做法是每个片段末尾允许追加一个空格,最后 trim();或者用列表收集非空片段,最后 String.join(" ", parts)

"Twenty " + helper(0) 可能得到 "Twenty "
trim 后变成 "Twenty"

面试中要说明自己有意识地处理空格,而不是让输出依赖偶然格式。

六、特殊数字 0

0 不能交给主循环处理,因为所有单位组都会被跳过,最后得到空字符串。应当在入口直接返回 "Zero"

if (num == 0) return "Zero";

这是一类典型的“空结果不等于正确结果”的边界条件。

七、复杂度分析

对 32 位整数来说,最多处理 Billion, Million, Thousand, 个位组 四组,每组递归深度固定,因此时间复杂度和空间复杂度都可视为 O(1)。如果泛化到任意长数字字符串,则时间复杂度与分组数量成正比。

八、递归 helper 的返回值约定

helper 最好约定为“返回没有首尾多余空格的英文片段”。这样主函数只负责在片段和单位之间加一个空格,最后再整体 trim。如果 helper 可能返回带前导空格或尾随空格的字符串,主流程会很难稳定控制格式。

helper(100) -> "One Hundred"
helper(101) -> "One Hundred One"
helper(110) -> "One Hundred Ten"
helper(1000) 不应该被调用,因为 helper 只处理三位组

这个约定能把问题边界压得很清楚:大单位由主函数处理,三位以内由 helper 处理,二者不互相抢职责。

九、为什么不用在英文里补 and

有些英语口语会说 One Hundred and One,但 LeetCode 273 的标准输出不包含 and,即 One Hundred One。因此实现时不要凭自然语言习惯额外插入单词,否则格式会错。

101
题目期望: One Hundred One
不要输出: One Hundred and One

面试中可以主动说明:本题不是做自然语言生成,而是按平台规定的格式做确定性转换。

十、从样例到代码的拆分路线

可以把 1234567891 作为完整手推样例:

1,234,567,891
1   -> One Billion
234 -> Two Hundred Thirty Four Million
567 -> Five Hundred Sixty Seven Thousand
891 -> Eight Hundred Ninety One

拼接后得到 One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One。这个样例同时覆盖 Billion、Million、Thousand、Hundred、十位和个位,是很好的自测用例。

八、常见误区与追问

  • 误区:逐位从左到右硬编码。 英文单位按三位分组,逐位硬编码会非常复杂且容易漏零。
  • 误区:没有特判 0。 主循环会跳过所有组,返回空字符串。
  • 误区:把 10 到 19 按十位加个位处理。 ElevenTwelveThirteen 等必须查特殊表。
  • 误区:输出中间零组。 One Million Ten 中不应该出现 Zero Thousand
  • 追问:为什么 LeetCode 输入只到 Billion? 因为 32 位 int 最大约 2.1 billion,单位到 Billion 足够。
  • 追问:如何支持更大整数? 把输入当字符串按三位切分,并扩展单位数组即可。

十一、加强记忆

  1. 英文数字每三位换一个大单位。
  2. 主函数拆 Billion / Million / Thousand / 个位组
  3. helper 只管 1..999,分成 <20<100>=100
  4. 零组跳过,数字 0 单独返回 Zero
  5. 字符串拼接要收尾去空格,避免格式错误。