问题陈述:
给定整数n,计算出小于或等于n的所有非负整数中出现的数字1的总数。
例如: 给定n = 13, 返回6,因为数字1出现在以下数字中:1,10,11,12,13。
高效解决方案:
location= location.split(' ').map(_.capitalize).mkString(" ")
我的问题:
我在其中一个论坛找到了问题的解决方案,我发现很难理解解决方案。我理解它非常简单,但请详细解释请帮助我。
谢谢
答案 0 :(得分:1)
因此,在您的问题中包含的代码中,digit
正在从右到左移动数字,而q
与x
的数量相对应,增加了10的幂,都在数量上。 while循环中的每个循环计算该位置中有多少个循环。让我们看一个例子:
n => 131
digit => 1, 3, 1
q => 13, 1, 0
x => 1, 10,100
q * x => 13*1
// there are 13 ones in the 10^0 position from 0 to 130 (13 counts of 10)
digit == 1 => n % 1 + 1 = 0 + 1 = 1
// there is 1 one in the 10^0 position from 131 to 131
(the remainder for the counts of 10)
---
q * x => 1*10
// there are 10 ones in the 10^1 position from 0 to 100 (1 count of 100): 10 to 19
digit == 3 => x = 10
// there are 10 ones in the 10^1 position from 101 to 131: 110 to 119
(the remainder for the counts of 100)
---
q * x => 0*100
// there are 0 ones in the 10^2 position from 0 to 0 (0 counts of 1000)
digit == 1 => n % 100 + 1 = 31 + 1
// there are 32 ones in the 10^2 position from 0 to 131
(the remainder for the counts of 1000)
答案 1 :(得分:0)
以下是解决此问题的一种方法:假设n < 10^k
,即n
可由k
十进制数字表示。让我们尝试构造所有具有k
或更少十进制数字的正数,其中包含1
个。
将2^k
放入某些1
位中有k
种可能性。
对于每个1
展示位置的选择,我们可以轻松统计所有最多k
位且且小于n
的正数。
例如,与yxxx1xx11x
模式匹配的所有数字,x
可以是0
或2-9
,y
2-9
}。请注意那里的特殊y
,因为如果y==0
,则x
之后的8 * 9^6
不允许为零。有3 * 8 * 9^6
种可能性。因此,此模式会为总计数提供1
,因为每个此类数字包含3 n
个。
这有点复杂,因为我们需要将数量限制为小于或等于y
的数字。这意味着并非x
和n=6239914230
的每个组合都有效。例如,如果y<=6
,y<6
和x
,则第一个{{1}}必须最多为2,等等......
答案 2 :(得分:0)
尝试在此处观察模式
考虑N = 2196,它有4位数字,位数分别为数十,数百和数千。
现在,尝试观察模式:
Numbers having 1 at ones position
1 11 21 31 41 51 ...
Numbers having 1 at tens position
10 110 210 310 ...
11 111 211 311 ...
......................
19 119 219 319 ...
Numbers having 1 at hundreds position
100 1100 2100 ...
101 1101 2101 ...
102 1102 2102 ...
....................
199 1199 2199 ...
您能看到一个由1个数字组成的集群,其周期为10的情况吗?
一个10个数字的簇,其时间周期为十以百计,一个100个数字的簇,时间周期为百以千计?
因此,我们的最终答案将是Summation of (N / Time Period) * Cluster Size
但是,请注意最后一种情况
如果N % Time Period != 0
,则还有一个集群将不完整。
尝试通过取N = 2196来弄清楚。
根据以上分析:
这是C ++代码
int solve(int A){
int ans = 0;
for(int i = 1; i <= A; i *= 10){
// i is cluster size.
// temp is time period.
int temp = i * 10;
// min(max(A%temp-i+1, 0), i) -> this part is going to take care
// of extra last cluster.
ans += ((A/temp) * i) + min(max(A%temp-i+1, 0), i);
}
return ans;
}