题目描述

✅ 1556. 千位分隔数

image-20260928220051372

题意分析

将非负整数从右向左每三位分成一组,用英文句点 . 连接各组,并返回字符串。只有最高位的一组可能不足三位,结果两端都不能有分隔点。

解法:从低位分组构造

核心思路

[!blue]

分组以最低位为起点,所以直接用 n % 10 取出当前最低位,再用 n /= 10 去掉它。这样不用先计算总位数,也不用单独判断最高组有几位。

count 记录自上一个分隔点以来已经写入的数字个数,更新后的 n 表示尚未处理的高位。每写满三位,只有 n > 0 时才追加一个点并清零 count:还有高位才有下一组,没有下一组就不需要分隔点。最高组不足三位时,循环直接结束即可。

数字按低位到高位写入,缓冲区整体与结果相反。在一组三位后插点,反转后就成为该组前面的分隔点;一次整体反转会同时恢复组的顺序和组内的数字顺序。输入为 0 时循环不会执行,因此要提前返回 "0"。

解题步骤

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

代码实现

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)$,用于保存数字和分隔点组成的结果。

关键点总结

[!green]

  • 分组从右端开始,最高位组的长度才无需特判。
  • 插点条件是 count == 3 && n > 0,其中 n > 0 专门避免前导分隔点。
  • 低位到高位的构造顺序与结果相反,因此最后必须反转。
  • 0 是唯一不会进入循环但仍需输出一位数字的输入。
  • 输入保证非负,不需要处理负号;数字中的零也要正常写入,不能因为当前余数是零就停止。

易错点总结

[!yellow]

  • 未特判 n == 0,会返回空字符串。
  • 只判断 count == 3,会在总位数是三的倍数时多出前导分隔点。
  • 插点后未把计数清零,后续就无法再次满足三位一组的条件。
  • 忘记反转,会把数字和各组的顺序都颠倒。
  • 使用逗号而不是题目要求的英文句点 .。

相似题目

题目 难度 关联与区别
482. 密钥格式化 简单 同样从右向左按固定长度分组输出;本题使用三位数字分组,密钥格式化还需跳过旧分隔符并统一大小写。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2025/19972271
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!