目录

题目描述

1556. 千位分隔数

题意分析

给一个非负整数,把它写成字符串,并且每三位数字之间插入一个点作为分隔符,返回这个字符串。注意分隔符是英文句点 .,不是常见的逗号。

要点在于「每三位」是从右往左数的,而不是从左往右。因为最高位那一组的长度取决于总位数模 3 的余数,可能是 1 位、2 位或 3 位,只有从低位开始数才能自动得到正确的分组。

约束信号是 n 最大到 2³¹ - 1,也就是十位数,位数很少,怎么写都不会超时;真正被考察的是边界处理是否干净,而不是效率。

边界包括:n = 0 时循环体一次都不会执行,必须保证返回 "0" 而不是空串;位数恰好是 3 的倍数时(比如 123456),最高位前面绝不能多出一个点;位数不足 4 位时(比如 987),一个点都不该出现。

解法:从低位分组构造

核心思路

千位分组必须从右端开始,因为最高位组可能只有 1 到 3 位。直接从低位取数:每轮用 n % 10 取出一位并写入缓冲区,用 n /= 10 删除这一位;每写满三位,若仍有更高位,就追加分隔点。

循环不变量是:缓冲区保存了已经处理的低位部分的逆序表示count 是当前组已写入的数字数。插点条件必须同时满足 count == 3n > 0:前者保证每组三位,后者保证最高位组前不会多出一个点。

因为数字按低位到高位写入,最后整体反转即可得到答案。n = 0 时循环不会执行,需要单独返回 "0"

解题步骤

  1. n == 0,直接返回 "0"
  2. 反复取 n % 10,把当前最低位追加到缓冲区,并令 n /= 10
  3. 当前组计数加一;当计数达到 3 且 n > 0 时追加 .,再把计数清零。
  4. 数字处理完后反转缓冲区并返回。

1234567 为例,低位方向依次写出 765.432.1,反转后得到 1.234.567。对于 123456,处理最高三位后 n 已为 0,因此不会在最前面多加分隔点。

代码实现

class Solution {
    public String thousandSeparator(int n) {
        if (n == 0) {
            return "0";
        }

        StringBuilder reversed = new StringBuilder();
        int count = 0;
        while (n > 0) {
            reversed.append((char) ('0' + n % 10));
            n /= 10;
            count++;
            if (count == 3 && n > 0) {
                reversed.append('.');
                count = 0;
            }
        }
        return reversed.reverse().toString();
    }
}
func thousandSeparator(n int) string {
    if n == 0 {
        return "0"
    }

    reversed := make([]byte, 0)
    count := 0
    for n > 0 {
        reversed = append(reversed, byte('0'+n%10))
        n /= 10
        count++
        if count == 3 && n > 0 {
            reversed = append(reversed, '.')
            count = 0
        }
    }

    for left, right := 0, len(reversed)-1; left < right; left, right = left+1, right-1 {
        reversed[left], reversed[right] = reversed[right], reversed[left]
    }
    return string(reversed)
}

复杂度分析

  • 时间复杂度:$O(d)$,其中 $d$ 是十进制位数;逐位处理和最终反转各扫描一次。
  • 空间复杂度:$O(d)$,用于保存数字和分隔点组成的结果。

关键点总结

  • 分组从右端开始,最高位组的长度才无需特判。
  • 插点条件是 count == 3 && n > 0,其中 n > 0 专门避免前导分隔点。
  • 低位到高位的构造顺序与结果相反,因此最后必须反转。
  • 0 是唯一不会进入循环但仍需输出一位数字的输入。

易错点总结

  • 未特判 n == 0,会返回空字符串。
  • 只判断 count == 3123456 会得到 .123.456
  • 插点后未把计数清零:1234567 只会产生一个分隔点。
  • 忘记反转:1234567 会返回 765.432.1
  • 使用逗号而不是题目要求的英文句点 .

相似题目

题目 难度 考察点
7. 整数反转 中等 逐位取模与溢出判断
8. 字符串转换整数 (atoi) 中等 状态机式字符串解析
12. 整数转罗马数字 中等 贪心按面值拆分
273. 整数转换英文表示 困难 三位一组的递归拼写
68. 文本左右对齐 困难 分组与末行特殊格式