Problem Link:https://www.nowcoder.com/practice/bd7f978302044eee894445e244c7eee6?tpId=13&tqId=11184&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
题目描述
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路:算法思想是这样的,求1~n整数中1出现的次数。假设n=21345,那么可以先划分为1~1345和1346~21345这两个区间。对于1346~21345这个区间,分成1346~11345和11346~21345这两段。然后先求出1346~21345范围内第一位不为1且后四位数中至少一位为1的总个数。根据排列组合,得2*4*10^3=8000。那么这里8000就是1346~21345范围内第一位不为1且后四位数中至少一位为1的总个数。再求出最高位(万位)为1的数目,相加就是1346~21345范围内的总数目。然后再采用相同方法,对1~1345进行递归求解。
AC code:
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
if(n==0)
{
return 0;
}
else if(n<10)
{
return 1;
}
int ans=0;
int wei=log10(n)+1;
int first = n/PowerBase10(wei-1);//最高位
int nextN=n%PowerBase10(wei-1);//余数
int numFirst;
int numOther;
if(first==1)
{
numFirst = nextN + 1;
}
else
{
numFirst= PowerBase10(wei-1);
}
numOther = first * (wei-1) * PowerBase10(wei-2);
ans += numFirst + numOther + NumberOf1Between1AndN_Solution(nextN);
return ans;
}
int PowerBase10(int n)
{
int res=1;
for(int i=1;i<=n;i++)
{
res*=10;
}
return res;
}
};