【问题标题】:Given a number n, find out how many numbers have digit 2 in the range 0...n给定一个数字 n,找出在 0...n 范围内有多少个数字为 2 的数字
【发布时间】:2012-06-22 13:12:24
【问题描述】:

这是一道面试题。

给定一个数字 n,找出在 0...n 范围内有多少个数字为 2 的数字

例如,

输入 = 13 输出 = 2(2 和 12)

我给出了通常的 O(n^2) 解决方案,但有没有更好的方法。

是否有任何“技巧”公式可以帮助我立即得到答案

【问题讨论】:

  • O(n²)?如果你的意思是,生成数字并检查数字,那就是 O(n lg n),因为每个数字 n 都由 O(lg n) 个数字表示。
  • 这是一个排列问题..
  • @FredFoo 每个数字由 log10(n) 位表示,所以它是 O(nlog10(n)) (以 10 为基数的位数是 log10(n))

标签: algorithm


【解决方案1】:

数一下有数字2的数。在小于10k的数中,正好有9k个.然后剩下的就是处理从 10kn 的数字,其中

10^k <= n < 10^(k+1)

您可以通过单独处理前两位数字来做到这一点(必须区分案例 2 和其他案例),然后是前两位数字等。

例如,对于n = 2345,我们发现有9^3 = 729 数字没有低于1000 的数字2。在1000 到1999 的范围内又有729 个这样的数字。然后在2000 到2345 的范围内,有没有,总共有 1458 个,因此包含数字 2 的数字是

2345 - 1458 = 887

【讨论】:

  • 你能解释一下你是怎么得到 9^k 个数字的吗,我不太擅长组合数学。
  • 如果你用前导零写数字,数字 0 到 10^k - 1 正是你可以用 k 数字写的数字。对于每个数字,有 9 个 (== 10 - 1) 可能的选择 (0,1,3,4,5,6,7,8,9)。选择是独立的,所以选择的总数是每个数字的选择数量的乘积,9*9*...*9 = 9^k。如果您在既不包含数字 2 也不包含数字 5 的数字之后,它将是 8^k (8 = 10 - 2)。同样的原则也适用于其他基数的表示。但是,由于数字实际上没有前导零,所以继续...
  • ...,禁止数字 0 略有不同。然后你不能添加前导零来使所有数字都具有相同的长度,并且10^k 以下没有数字 0 的数字的计数是9^1 + 9^2 + 9^3 + ... + 9^k = 9 * (9^k - 1)/8。如果你禁止 0 和 d 其他数字,留下 e = 9-d 符合条件的数字,你会得到 e^1 + e^2 + ... + e^k = e * (e^k - 1)/(e-1)。 (对于 10 以外的碱基,将 9 替换为 base-1。)
【解决方案2】:

argument 'digit' 是我们要计数的那个,arg 'number' 是直到我们要计数的地方。例如:如果我们要统计 '1' 的出现次数,从 0 到 12,调用 digit=1,number=12 的函数,它会返回 '1' 的出现次数。

int countOccurrences(int digit, int number)
{
    int counter = 0;
    for(int i=1; i<number; i++)
    {
        int j = i;
        while(j > 0)
        {
            if(j%10 == digit)
                counter++;
            j /= 10;
        }
    }
    return counter;
}

【讨论】:

  • 你试过执行这个方法吗?它在 countOccurrences(1,20) 上返回 12,而不是 3。
  • 这计算的是二,而不是有多少个数字有二。例如。当它达到 22 时,它会增加两次,而不是一次,这是错误的。
【解决方案3】:

给定带有数字 ABCDEF 的数字,您可以计算 [0,F], [0,E9], [0,D99], [0,C999], [0,B9999][0,A99999] 范围内的“2”的数量并将它们相加。

那么对于范围[0, X9999...999],上面的数字T = X9999...999可以写成(X+1) * 10&lt;sup&gt;nines&lt;/sup&gt; -1

该范围内 '2' 的数量为:

((X >= 2 ? 1/(X + 1)) : 0) + nines/10 ) * (T + 1);

即:如果X &gt;= 2,则在 9+1 位置有“2”的数字的比例是1/(X+1),在该位置总共有(T+1)/(X+1)“2”。如果X &lt; 2,则 [0..T] 上的数字在该位置没有“2”。

对于其他数字位置,很容易看出在每个数字位置,1/10的数字都有一个'2',所以位置0有(T+1)/10'2',(T+1)/10'2'在位置1等。一共(T+1) * nines / 10

这个解决方案的复杂度是 O(logN)。

【讨论】:

    【解决方案4】:

    这就是我编写初稿(Python 代码)的方式

    def count2(n) :
        return [p for p in range(n+1) if '2' in str(p)]
    

    这将返回一个包含编号的列表。

    在性能方面还不错,对于 n=10,000,000,平均迭代大约需要 5.5 秒

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-05
      • 2015-09-16
      • 1970-01-01
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多