美文网首页
整数中1出现的次数

整数中1出现的次数

作者: 小小的白菜 | 来源:发表于2018-09-19 19:41 被阅读0次

    求出 1~13 的整数中1出现的次数,并算出 100~1300 的整数中1出现的次数?为此他特别数了一下 1~13 中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

    思路一:求每一个数中含有的“1”的个数,累加。

    function NumberOf1Between1AndN_Solution(n) {
        if(typeof n !== 'number') return false
        let count = 0
        for(let i = 1; i <= n; i++) {
          let strNum = i.toString()
          for(let j = 0; j < strNum.length; j++) {
            if(strNum.charAt(j) === '1') {
              count++
            }
          }
        }
        return count
      }
    

    思路二:
    一个更好的办法是利用数学公式直接计算出最终的结果,该方法是依次求出数字 X 在个位、十位、百位等等出现的次数,再相加得到最终结果。博客地址

    • 从 1 至 10,在它们的个位数中,任意的 X 都出现了 1 次。
    • 从 1 至 100,在它们的十位数中,任意的 X 都出现了 10 次。
    • 从 1 至 1000,在它们的千位数中,任意的 X 都出现了 100 次。

    依此类推,从 1 至 10^i,在它们的左数第二位(右数第 i 位)中,任意的 X 都出现了 10^(i−1) 次。

    接下来以 n=2593,X=5 为例来解释如何得到数学公式。从 1 至 2593 中,数字 5 总计出现了 813 次,其中有 259 次出现在个位,260 次出现在十位,294 次出现在百位,0 次出现在千位。

    现在依次分析这些数据,首先是个位。从 1 至 2590 中,包含了 259 个 10,因此任意的 X 都出现了 259 次。最后剩余的三个数 2591, 2592 和 2593,因为它们最大的个位数字 3 < X,因此不会包含任何 5。

    然后是十位。从 1 至 2500 中,包含了 25 个 100,因此任意的 X 都出现了 25×10=250 次。剩下的数字是从 2501 至 2593,它们最大的十位数字 9 > X,因此会包含全部 10 个 5。最后总计 250 + 10 = 260。

    接下来是百位。从 1 至 2000 中,包含了 2 个 1000,因此任意的 X 都出现了 2×100=200 次。剩下的数字是从 2001 至 2593,它们最大的百位数字 5 == X,这时情况就略微复杂,它们的百位肯定是包含 5 的,但不会包含全部 100 个。如果把百位是 5 的数字列出来,是从 2500 至 2593,数字的个数与百位和十位数字相关,是 93+1 = 94。最后总计 200 + 94 = 294。

    最后是千位。现在已经没有更高位,因此直接看最大的千位数字 2 < X,所以不会包含任何 5。到此为止,已经计算出全部数字 5 的出现次数。

    总结一下以上的算法,可以看到,当计算右数第 i 位包含的 X 的个数时:

    • 取第 i 位左边(高位)的数字,乘以 10i−1,得到基础值 a。
    • 取第 i 位数字,计算修正值:
      • 如果大于 X,则结果为 a+10^(i−1)。
      • 如果小于 X,则结果为 a。
      • 如果等 X,则取第 i 位右边(低位)数字,设为 b,最后结果为 a+b+1。
    // 计算数字 X 在 1-n 中出现的次数。
    int count(int n, int x) {
        int cnt = 0, k;
        for (int i = 1;k = n / i;i *= 10) {
            // k / 10 为高位的数字。
            cnt += (k / 10) * i;
            // 当前位的数字。
            int cur = k % 10;
            if (cur > x) {
                cnt += i;
            } else if (cur == x) {
                // n - k * i 为低位的数字。
                cnt += n - k * i + 1;
            }
        }
        return cnt;
    }
    

    参考地址

    http://www.cnblogs.com/cyjb/p/digitOccurrenceInRegion.html

    相关文章

      网友评论

          本文标题:整数中1出现的次数

          本文链接:https://www.haomeiwen.com/subject/iyainftx.html