《编程之美 》2.4
问题:给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数。
解法一:从1到N遍历,求每个数中1的个数加和
代码1:
int Count1InAInteger(int n)
{
int iNum = 0;
while (n != 0)
{
iNum += (n % 10 == 1) ? 1 : 0;
n /= 10;
}
return iNum;
}
int Count1OfAll(int n)
{
int iCnt = 0;
for(int i = 1; i <= n; i++)
{
iCnt += Count1InAInteger(i);
}
return iCnt;
}
解法二:
从1到N将每一位上1的个数加和
对于当前位,规律:
1. 如果当前为0,则此位上出现1的次数只由更高位决定,且等于更高位数字*当前位数。如12013中的百位出现1的个数为12*100;
2. 如果当前为1,则此位上出现1的次数不仅受更高位影响,还受低位影响。等于更高位数字*当前位数+低位数字+1。如12113中的百位出现1的个数为12*100+13+1(编程之美上这地方是不是有点小错误?);
3.其他情况,则此位上出现1的次数仅由高位决定,且等于(更高位数字+1)*当前位数。如12213中的百位出现1的次数为(12+1)*100。
代码2:
int Sum1s(int n)
{
int iCnt = 0;
int iFactor = 1;
int iLowerNum = 0;
int iCurrNum = 0;
int iHigherNum = 0;
while(n / iFactor)
{
iLowerNum = n - (n / iFactor) * iFactor;
iCurrNum = (n / iFactor) % 10;
iHigherNum = n / (iFactor * 10);
switch(iCurrNum)
{
case 0:
iCnt += iHigherNum * iFactor;
break;
case 1:
iCnt += iHigherNum *iFactor + iLowerNum + 1;
break;
default:
iCnt += (iHigherNum + 1) * iFactor;
break;
}
iFactor *= 10;
}
return iCnt;
}
REF:
1,编程之美
2,http://blog.csdn.net/cxllyg/article/details/7593344