题目:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
此题我是全程懵逼的,开始想到找规律,各种找,以前貌似找过,其实是有的,但是找的过程很复杂,想的有没有更好的方法。然后看了解法,书上有个地方写错了,导致我琢磨了好久。。。浪费了不少时间。
该题的思路是,假设一个数21345,首先考虑最高位2。因为它大于1,所以可以从10000-19999这总共有一万个1,具体个数时10的(len-1)个。当然也不是每个5位数都有这么多。如果最高位只是1,比如说12345,就只有2346个1了。
考虑完万位上的一,再考虑其它四位的1,四位中只要有一位是1,其它三位为0-9均可,此时含有10的3次方位。总共的1的个数为C(4,1)*(10的3次方),再考虑万位有几个,再乘以几。故总的个数是万位数字*4*1000;
考虑完最高位,低位只需要递归考虑即可。
代码如下:
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
stringstream ss;
ss<<n;
return NumberOf1(ss.str());
}
int NumberOf1(string str)
{
if(str==" ")
return 0;
if(str.size()==1&&str[0]-'0'==0)
return 0;
if(str.size()==1&&str[0]-'0'>0)
return 1;
//假设str是21345;
//numFirstDigit是10000-19999中第一个位中的数目
int numFirstDigit=0;
int len=str.size();
if(str[0]-'0'>1)
numFirstDigit=PowerBase10(len-1);
else if(str[0]-'0'==1)
{
int num;
string s=str.substr(1,str.size()-1);
stringstream ss(s);
ss>>num;
numFirstDigit=num+1;
}
//diwei是除最高位其它位含有的1的个数
int diwei=(str[0]-'0')*(len-1)*PowerBase10(len-2);
//qita是1-1345中的数目
int qita=NumberOf1(str.substr(1,str.size()-1));
return numFirstDigit+diwei+qita;
}
int PowerBase10(int n)
{
int i,result=1;
for(i=0;i<n;i++)
{
result*=10;
}
return result;
}
};