📌  相关文章
📜  国际空间研究组织 | ISRO CS 2017 – 5 月 |问题 5(1)

📅  最后修改于: 2023-12-03 15:37:15.791000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2017 – 5 月 |问题 5

题目描述

给定一个整数n,我们需要计算从数字 1 到 n 中所有数字中的 1 的总数。

输入

一个整数n(1 <= n <= 10^9)。

输出

输出从数字 1 到 n 中所有数字中的 1 的总数。

示例

输入:13

输出:6

解释:从 1 到 13,数字 1 出现了6次(1、10、11、12、13)。

思路

这道题可以用数学的方法来解决。我们可以将数字拆分成位数,然后分别计算每一位上 1 的出现次数,最后求和即可。

以数字 1234 为例:

  • 第一位上出现 1 的次数有 100 次(1~100,100~199,…,1100~1199,1200~1234)。
  • 第二位上出现 1 的次数有 10 次(100,101,…,109)。
  • 第三位上出现 1 的次数有 5 次(111,112,…,119)。
  • 第四位上出现 1 的次数有 1 次(1234)。

所以总共一共出现了 100 + 10 + 5 + 1 = 116 次 1。

代码实现
def countDigitOne(n: int) -> int:
    count = 0
    factor = 1
    while n // factor != 0:
        # 拆分当前位的数
        cur = (n // factor) % 10
        # 计算高位
        high = n // (factor * 10)
        if cur == 0:
            count += high * factor
        elif cur == 1:
            count += high * factor + n % factor + 1
        else:
            count += (high + 1) * factor
        factor *= 10
    return count

代码说明:

首先初始化计数器 count 和因子 factor,初始化时因子为 1(代表个位上的因子)。

接下来使用一个 while 循环,计算每一个位上出现 1 的次数。

在循环中,首先找出当前位的数字 cur 和高位的数字 high。

如果当前位的数字为 0,说明这一位没有 1 出现,直接将高位数字乘以因子加入到计数器中。

如果当前位的数字为 1,说明这一位有一部分数字必然会出现 1,直接将高位数字乘以因子加入到计数器中,并且还需要加上当前位后面的数字加 1(因为当前位为 1,所以后面的数字在 0~9 中都有可能出现)。

如果当前位的数字大于 1,说明这一位上所有的数字都会出现 1,直接将高位数字加 1 后乘以因子加入到计数器中。

最后因子乘以 10,用于计算下一位。循环结束后,将计数器 count 返回即可。

代码片段中使用了类型注解和文档字符串来加强代码的可读性和可维护性。返回的格式为 markdown,方便在文档中展示和阅读。