因为自己想的思路和网络上广泛的思路不一样,所以写一下我的思路,验证结果是正确的
题目如下:输入一个整数N,求从1-N这N个整数的十进制表示中1出现的次数,例如输入12,从1到12这些整数中包含1的数字有1,10,11,12, 1 一共出现了5次。
(Google面试题目)
用两个数字简述我的思路 例如输入为 7111
从1-7111可以分解成1-6999 和 111
这个数字的第一个数是7 大于1,所以从1000-1999这些数字里都多了一个1
所以NumOfOnes(7111) = NumOfOnes(111) + 7 * NumOfOnes(999) + 1000
之后求811和999可以用递归的方法。
不过需要注意的是,当第一个数字为1的时候,例如111,算法要执行另外一个分支
111可以分为1-99,100-111,100-111里面含有的1个个数是 (111-100 + 1) + NumOfones(11)
所以最后算法写成
NumOfOnes(111) = NumOfOnes(99) + 111 - 100 + 1 + NumOfOnes(11)
最后写程序如下:
void ParseNumber(int num, int &nDigits, int &nFirst, int &nOthers, int &nMaxDigits)
{
nDigits = 0;
int origNum = num;
while(num >= 10)
{
num /= 10;
nDigits ++;
}
nFirst = num;
nMaxDigits = pow(10.0,nDigits) ;
nOthers = origNum - nMaxDigits * nFirst;
nMaxDigits -= 1;
}
int GetNumOfOnes(int N)
{
if( N == 0)
{
return 0;
}
if( N < 10 )
{
return 1;
}
int nDigits, nFirst, nOthers, nMaxDigits;
ParseNumber(N, nDigits, nFirst, nOthers, nMaxDigits);
if( nFirst == 1)
{
return GetNumOfOnes(nMaxDigits) + nOthers + 1 + GetNumOfOnes(nOthers);
}
else
{
return pow(10.0, nDigits) + (nFirst) * GetNumOfOnes(nMaxDigits) + GetNumOfOnes(nOthers);
}
}