首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-07-08:统计区间内奇妙数的数目。用go语言,给定一个正整数 n,我们要考虑从 1 到 n 之间(包括 1 和 n)的所有整数。对每个数,按

2026-07-08:统计区间内奇妙数的数目。用go语言,给定一个正整数 n,我们要考虑从 1 到 n 之间(包括 1 和 n)的所有整数。对每个数,按

作者头像
福大大架构师每日一题
发布2026-07-08 16:50:37
发布2026-07-08 16:50:37
50
举报

2026-07-08:统计区间内奇妙数的数目。用go语言,给定一个正整数 n,我们要考虑从 1 到 n 之间(包括 1 和 n)的所有整数。对每个数,按照常见的千位分隔习惯写成字符串:从个位开始向左数,每三位插入一个逗号,但如果这个数不足四位(也就是小于 1000),则不加任何逗号。问题是:把 1 到 n 这 n 个数的这种书写形式连起来看,总共出现了多少个逗号?请计算出这个总数。

1 <= n <= 100000。

输入: n = 1002。

输出: 3。

解释:

数字 "1,000"、"1,001" 和 "1,002" 每个都包含一个逗号,总计 3 个逗号。

题目来自力扣3870,3871。

一、函数 countCommas(n int64) 分步逻辑拆解

步骤1:定义变量k,k代表每个数字固定拥有的逗号个数档位

k 是完整千位段的数量,对应数字统一携带的逗号数量:

  • • 数字区间 [10^(3m), 10^(3m+3)-1] 内所有数,都固定有 m 个逗号 m=0:1999,k=0,无逗号 m=1:1000999999,k=1,1个逗号 m=2:1000000~999999999,k=2,2个逗号 以此类推

步骤2:计算k的核心逻辑

2.1 特殊边界说明

当 n = 10^15 时,浮点数 math.Log10 会存在精度丢失,无法正确算出位数,因此代码预设兜底 k=5;题目限制 n≤100000,不会触发该特判,仅为超大数兼容。

2.2 常规n<1e15时的k计算流程

  1. 1. 将整数n转为浮点数,调用 math.Log10 得到n的十进制位数减1: 例 n=1002,log10(1002)≈3.000867
  2. 2. 对结果取整数,得到数字总位数减1:int(3.000867)=3
  3. 3. 整除3,得到完整千位段数量k:3 / 3 = 1 含义:1002属于1000~999999区间,每个数字固定1个逗号,k=1

步骤3:拆分总逗号的数学公式推导

总逗号 = 两部分相减: 总逗号 = k × (n + 1) − 前k个完整千位区间全部数字产生的逗号总和

第一部分:k × (n+1)

假设从1到n所有数字都有k个逗号,先算出理论最大值。 示例 n=1002,k=1:1 × (1002+1) = 1003 含义:假设1~1002每个数字都带1个逗号,合计1003个逗号。

第二部分:(10^(3k+3) − 1000) / 999

这一步计算1 ~ (10^(3k)-1) 所有数字实际不含k个逗号的总差值,也就是需要扣除的无效逗号数量。

  1. 1. 3k:完整千位段对应的位数偏移,k=1时 3k=3
  2. 2. 3k+3 = 6,10^6 = 1000000
  3. 3. 10^6 − 1000 = 999000
  4. 4. 除以999:999000 / 999 = 1000 含义:1~999 这1000个数字,本身没有1个逗号,前面理论计算时给它们全部算了1个逗号,多算了1000个,需要全部减去。

步骤4:合并公式计算最终答案

代入示例 n=1002: 总逗号 = 1003 − 1000 = 3,和题目输出完全匹配。

通用公式数学意义

  1. 1. k 代表当前数字档位的标准逗号数;
  2. 2. k*(n+1):给1~n全部数字强制分配k个逗号,得到高估总和;
  3. 3. 减数项:统计所有小于10^(3k)的数字总个数,这些数字本身不足k个逗号,全部是多算的部分,需要扣除;
  4. 4. 相减后得到真实总逗号数量。

步骤5:main函数执行流程

  1. 1. 定义输入n=1002,转为int64类型传入countCommas;
  2. 2. 执行上述数学计算得到结果;
  3. 3. 打印输出最终逗号总数。

二、整体算法核心思想总结

不暴力遍历1~n逐个统计(避免循环),利用十进制千位分段数学公式直接计算,按数字所在区间批量统计逗号:

  1. 1. 先确定当前数字所在千位分段,得到该分段标准逗号数k;
  2. 2. 用整体高估法,统一给所有数字分配k个逗号;
  3. 3. 减去低位区间(不足k个逗号)的数字总数,修正高估误差;
  4. 4. 一步算出总逗号,无循环、无逐一枚举。

三、时间复杂度 & 额外空间复杂度分析

1. 时间复杂度 O(1)

整个计算仅执行常数次数学运算:log10、整数转换、幂运算、四则加减乘除,不存在循环、递归、遍历操作,运算次数不随n的大小变化,固定常数次计算,时间复杂度为常量级 O(1)。

2. 额外空间复杂度 O(1)

函数内部仅定义固定数量局部变量(k、ans,无动态数组、切片、哈希、递归栈等动态内存),分配的内存空间大小与输入n无关,始终为固定常量空间,额外空间复杂度 O(1)。

Go完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
    "math"
)

func countCommas(n int64) (ans int64) {
    k := 5// n == 1e15 时 Log10(n) 有误差,需要特判
    if n < 1e15 {
        k = int(math.Log10(float64(n))) / 3
    }
    returnint64(k)*(n+1) - (int64(math.Pow10(k*3+3))-1000)/999
}

func main() {
    n := 1002
    result := countCommas(int64(n))
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

def count_commas(n: int) -> int:
    """
    返回从 1 到 n(含)所有整数的标准书写格式中逗号的总数
    """
    if n < 1000:
        return0
    # k 表示最高位的逗号组数,例如 n=1000 时 k=1,n=1_000_000 时 k=2
    k = (len(str(n)) - 1) // 3
    # 使用公式:k*(n+1) - (10^(3k+3) - 1000) / 999
    pow10 = 10 ** (3 * k + 3)
    return k * (n + 1) - (pow10 - 1000) // 999


if __name__ == "__main__":
    n = 1002
    result = count_commas(n)
    print(result) 
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

.

代码语言:javascript
复制
#include <iostream>
#include <cmath>
#include <cstdint>

int64_t countCommas(int64_t n) {
    int k = 5;  // 当 n >= 1e15 时直接取 5,避免 log10 的精度误差
    constexpr int64_t threshold = 1000000000000000LL; // 1e15
    if (n < threshold) {
        k = static_cast<int>(std::log10(static_cast<double>(n))) / 3;
    }
    int64_t pow10 = static_cast<int64_t>(std::pow(10.0, k * 3 + 3));
    return static_cast<int64_t>(k) * (n + 1) - (pow10 - 1000) / 999;
}

int main() {
    int64_t n = 1002;
    int64_t result = countCommas(n);
    std::cout << result << std::endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述

·


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、函数 countCommas(n int64) 分步逻辑拆解
    • 步骤1:定义变量k,k代表每个数字固定拥有的逗号个数档位
    • 步骤2:计算k的核心逻辑
      • 2.1 特殊边界说明
      • 2.2 常规n<1e15时的k计算流程
    • 步骤3:拆分总逗号的数学公式推导
      • 第一部分:k × (n+1)
      • 第二部分:(10^(3k+3) − 1000) / 999
    • 步骤4:合并公式计算最终答案
      • 通用公式数学意义
    • 步骤5:main函数执行流程
  • 二、整体算法核心思想总结
  • 三、时间复杂度 & 额外空间复杂度分析
    • 1. 时间复杂度 O(1)
    • 2. 额外空间复杂度 O(1)
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档