Description
Count the number of k's between 0 and n. k can be 0 - 9.
Example
if n = 12
, k = 1
in
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
we have FIVE 1's (1, 10, 11, 12)
========================== 华丽分割线 ==========================
实现思路:
介于遍历 0 ~ n,统计每个数字中 k 出现的次数思路处理有些低效,所以就不作实现。
按位求解,依次求出个位,十位,百位,千位 ......可能出现 k 的次数,求和。
分析:
(举个简单栗子 n = 222, k = 1 或 2 或 3)
个位:
个位数字就是 n % 10 = 2;
(假设:n = 222, k = 1) n % 10 > k
那么个位出现 1 的所有情况就是: 001,011,021,... ...,091 ;101,111,... ...,191;201,211;221;
总共就是 10 + 10 + 2 + 1。 即 (n / 10 + 1 )x 1 ( 个位数 )。
( 假设:n = 222, k = 2 ) n % 10 == k
那么个位出现 2 的所有情况就是:002,012,022,... ...,092;102,112,... ...,192;202,212;222;
总共就是 10 + 10 + 2 + 1。 即 (n / 10 )x 1 ( 个位数 ) + 1。
( 假设:n = 222, k = 3 ) n % 10 < k
那么个位出现 3 的所有情况就是:003,013,023,... ...,093;103,113,... ...,193;203,213;
总共就是 10 + 10 + 2。 即 (n / 10 )x 1 ( 个位数 ) 。
十位:
十位数字就是 n / 10 % 10 = 2;
(假设:n = 222, k = 1) n / 10 % 10 > k
那么十位出现 1 的所有情况就是:010,011,012,... ...,019;110,111,... ...,119;210,211,... ...,219;
总共就是 10 + 10 + 10 。即 (n / 10 / 10 + 1 ) x 10 ( 十位数 )
(假设:n = 222, k = 2) n / 10 % 10 == k
那么十位出现 2 的所有情况就是:020,021,022,... ...,029;120,121,... ...,129;220,221,222;
总共就是 10 + 10 + 2 + 1 。即 (n / 10 / 10 ) x 10 ( 十位数 ) + 2 + 1
(假设:n = 222, k = 3) n / 10 % 10 < k
那么十位出现 3 的所有情况就是:030,031,032,... ...,039;130,131,... ...,139;
总共就是 10 + 10。即 (n / 10 / 10 ) x 10 ( 十位数 )
百位:
百位数字就是 n / 10 / 10 % 10 = 2;
(假设:n = 222, k = 1) n / 10 / 10 % 10 > k
那么百位出现 1 的所有情况就是:100,101,102,... ...,199;
总共就是 100 。即 (n / 10 / 10 / 10 + 1 ) x 100 ( 百位数 )
(假设:n = 222, k = 2) n / 10 / 10 % 10 == k
那么百位出现 2 的所有情况就是:200,201,202,... ...,222; 总共就是 22 + 1。即 (n / 10 / 10 / 10 ) x 100 ( 百位数 ) + ( 1 x 22 ) + 1
(假设:n = 222, k = 3) n / 10 / 10 % 10 < k
那么百位出现 3 的所有情况就是:;
总共就是 0。即 (n / 10 / 10 / 10 ) x 100 ( 百位数 )。
注:有千位,万位,百万位等等依此类推
总结通用计算方式:
引入变量 ( ulBitWeight ) 位权
(
当计算位置在个位时, ulBitWeight = 10 ^ 0
当计算位置在十位时, ulBitWeight = 10 ^ 1
当计算位置在百位时, ulBitWeight = 10 ^ 2
.... ....
)
if( n / ulBitWeight % 10 > k )
k 在当前位所出现的总共次数为:( n / ulBitWeight / 10 + 1 ) * ulBitWeight
if( n / ulBitWeight % 10 == k )
k 在当前位所出现的总共次数为:( n / ulBitWeight / 10 ) * ulBitWeight + n % ulBitWeight + 1
if( n / ulBitWeight % 10 < k )
k 在当前位所出现的总共次数为:( n / ulBitWeight / 10 ) * ulBitWeight
k 出现的次数就是各位置出现次数之和。
* 处理两个特殊情况 *
1、如果 k == 0, k 出现的次数 = n / 10 + 1;
2、如果 k != 0, n == 0,k 出现的次数 = 0;
代码:
int digitCounts(int k, int n) {
// write your code here
int ulSum = 0; // k 出现的次数
int ulBitWeight = 0; // 位权,个位为 10^0, 十位为,10^1, 百位为 10^2, 千位为 10^3 ... ... 依此类推
// 特殊情况处理 k == 0, n == 0
if( k == 0 )
{
return n / 10 + 1;
}
else if( n == 0 )
{
return 0;
}
while( n > ulBitWeight )
{
// 位权处理,不使用 float 库函数 pow
if( ulBitWeight == 0 )
{
ulBitWeight = 1; // 巧妙处理,利用初始值特殊处理个位 位权
}
else
{
ulBitWeight *= 10; // 其它位权处理
}
if( n / ulBitWeight % 10 > k )
{
ulSum += ( n / ulBitWeight / 10 + 1 ) * ulBitWeight;
}
else if( n / ulBitWeight % 10 == k )
{
ulSum += ( n / ulBitWeight / 10 ) * ulBitWeight + n % ulBitWeight + 1;
}
else if( n / ulBitWeight % 10 < k )
{
ulSum += ( n / ulBitWeight / 10 ) * ulBitWeight;
}
}
return ulSum;
}