这道题的意思是,给定一个数n,那么从1到n这n个数中,1出现了几次。这个问题开始看,肯定不容易做,往往都是利用最笨的方法,一个数一个数的找就行了,那么如果n很大,就需要非常多的时间了,书中提供了更好的方法,需要发现数字中存在的相关规律:
对于数abcde,c这位出现1的次数分以下情况:
1.若c > 1,结论是(ab + 1)* 100;
2.若c == 1,结论是(ab)* 100 + de + 1;
3.若c < 1,结轮是 ab * 100 + de + 1;
上面的意思就是,对于每一位出现1的情况都和它的高位和低位是相关的,所以,我们只要获取当前位,高位,低位就可以了,所以,首先,给出函数定义:
/*2.4 1的数目*/
int DutCountOf1InN(int);
之后,我们利用上面的公式很容易写出如下简单的代码:
/*
* 对于数abcde,c这位出现1的次数分以下情况:
* 1.若c > 1,结论是(ab + 1)* 100;
* 2.若c == 1,结论是(ab)* 100 + de + 1;
* 3.若c < 1,结轮是 ab * 100 + de + 1;
*/
int DutCountOf1InN(int n)
{
if (n <= 0)
return 0;
int count = 0;
/*乘数因子,以10倍递增*/
int factor = 1;
int lowerNum = 0;
int currNum = 0;
int highNum = 0;
while (n / factor != 0)
{
/*低位数字*/
lowerNum = n - (n / factor) * factor;
/*当前位数字*/
currNum = (n / factor) % 10;
/*高位数字*/
highNum = n / (factor * 10);
switch (currNum)
{
case 0:
count += highNum * factor;
break;
case 1:
count += highNum * factor + lowerNum + 1;
break;
default:
count += (highNum + 1) * factor;
break;
}
factor *= 10;
}
return count;
}
这个问题到这里还没有结束,假如,题目问的不是1的个数,而是2,3.。。。的个数呢,还是一样的解决办法吗?经过分析,我们发现,依然是利用上面的那个公式就可以了,所以,利用下面的代码可以得到c的个数,当然c是属于[1,9]:
函数声明
/*c的数目*/
int DutCountOfCInN(int, int);
源代码:
/*
*对于数abmde,m这位出现c的次数分以下情况:
* 1.若m > c,结论是(ab + 1)* 100;
* 2.若m == c,结论是(ab)* 100 + de + 1;
* 3.若m < c,结轮是 ab * 100 + de + 1;
*/
int DutCountOfCInN(int N, int c)
{
if (N <= 0)
return 0;
int sum = 0;
int low = 0, cur = 0, high = 0;
int ifactor = 1;
while (N / ifactor != 0)
{
low = N - (N / ifactor) * ifactor;
cur = (N / ifactor) % 10;
high = (N / ifactor) / 10;
if (cur < c)
{
sum += high * ifactor;
}
else if (cur == c)
{
sum += high * ifactor + low + 1;
}
else
{
sum += (high + 1) * ifactor;
}
ifactor *= 10;
}
return sum;
}