查找多少次" 2"发生在从0到n的所有数字中。
示例:n
= 112 answer
= 22
numbers : 2 , 12 , 20-29 , 32 ... 92 , 102 , 112
我想出了以下方法:
让k
= n的位数
f(k)
=从0
到10^k-1
的两个人的数量..
f(1)= 1 // 2
f(2)= 10 * f(1)+ 10 ^(2-1)// 12,20-29,32 ... 92
f(3)= 10 * f(2)+ 10 ^(3-1)
等等...
twos(int n , int k)
{
if(n<2)
return 0;
else if(n<10)
return 1;
msb = n/10^k
remainder = n%10^k
if(msb==2) // eg 230 , calculate 200 ... to 230 , and find twos from 0 on 199 and recursion on 30
return msb*(f(k)) + (remainder+1) + twos(remainder) // 2*(below 100) + 31 + tows(30)
else if (msb>=3)
return msb*(f(k)) + (10^k) + twos(remainder) // for 312 -> 3*(below 100) + 100 + twos(12)
else
return msb*(f(k)) + twos(remainder)
}
我的方法是否正确?
如果是这样,有没有比这更快的解决方案?
编辑:
对于这些测试用例,我的方法似乎是正确的,here是模拟
results
:
第一个颜色:n,第二个颜色:蛮力,第三个颜色:我的方法
2 1 1 5 1 1
91 19 19
868 277 277
7783 3359 3359
55576 32718 32718
293911 242093 242093
10179297 7091858 7091858
59939789 51975959 51975959
答案 0 :(得分:1)
令f(k)
为数字2的出现次数,从0到10^k-1
的数字(即最多k位数字)。
请注意,当将数字从k-1增加到k时,我们对每个新的前导数字都有f(k-1)个出现,加上前导数字本身的10 ^(k-1)个出现:
f(k) = 10*f(k-1) + 10^(k-1)
(这正是你的公式)
解决这种复发问题:
f(k) = k * 10^(k-1)
例如:
f(1) = 1
f(2) = 20
f(3) = 300
f(4) = 4000
...
实际上有一种不同的方法来获得这个公式。考虑所有k位数字(缺少的前导数字用零替换)。数字的数量是10 ^ k,每个数字都有k个数字,因此我们总共有k*10^k
个数字。现在,每个可能的数字都显示相同的次数,即k*10^k / 10 = k*10^(k-1)
。
- 编辑 -
以下Java解决方案使用上面的公式,并解决了O(log n)时间内任意n的问题:
// Counts occurrences of digit 2 in numbers less than n
public static int count(int n) {
int count = 0;
int factor = 1;
int pos = 0;
while (true) {
int m = n / factor;
if (m == 0) //Past last digit
break;
int d = m % 10;
count += d * pos * factor / 10;
if (d == 2)
count += n % factor;
else if (d > 2) {
count += factor;
}
factor = 10 * factor;
pos++;
}
return count;
}
答案 1 :(得分:1)
假设数字由数字n=... n4 n3 n2 n1
组成。我们希望查看所有数字x<=n
并计算其中的数字2
。 x
应表示为x=... x4 x3 x2 x1
。首先,我们计算有多少数字的最后一位数为x1==2
:
f1(n) = (n+8) / 10
假设分割截断。一些例子:
f1(1) = 0
f1(2) = 1
f1(12) = 2
f1(21) = 2
f1(22) = 3
现在让我们计算一个倒数第二位的数字x2==2
。这类似于切割n
的最后一位数字,然后计算最后两位数字的数字:
f2(n) = 10 * f1(n/10) # almost right
让我们测试一下:
f2(10) = 0
f2(20) = 10 * f1(2) = 10 # wrong
f2(25) = 10 * f1(2) = 10 # wrong
f2(29) = 10 * f1(2) = 10
f2(30) = 10 * f1(3) = 10
当n
的倒数第二位是{2}本身n2==2
时,我们需要对此案例进行特殊处理:
f2(n) = 10*f1(n/10) - 9 + n1 # if n2==2
使用n1 == n % 10
(余数函数),可以写成:
f2(n) = 10*f1(n/10) - 9 + n%10 # if n2==2
类似于计算x3==2
:
f3(n) = 100*f1(n/100) # if n3 != 2
f3(n) = 100*f1(n/100) - 99 + n%100 # if n3 == 2
总结我们得到的总数为2:
f(n) = f1(n) + f2(n) + f3(n) + ...
在Java中:
public static int count2(int n) {
int res = (n+8) / 10;
int divider = 10;
while (n>= 2*divider){
int na = n / divider;
res = res + divider * ((na+8) /10);
if (na%10==2)
res = res - divider + 1 + n % divider;
divider = divider * 10;
}
return res;
}