//by L&L
//《剑指offer》面试题32,P174
//问题:从1到n整数中1出现的次数
//
//非递归方法描述:
//先取一个具体的例子,假设n = 9999;
//令个位为1,则有(999+1)*1个数;
//令十位为1,则有(99 +1)*10个数;
//令百位为1,则有(9 +1)*100个数;
//令千位为1,则有(0 +1)*1000个数;
//以上相加,得...共4000
//上面这个例子太特殊,再看一个更具普遍性的例子:
//假设n = 2014:
//令个位为1,则有(201+1)*1个数;
//令十位为1,则有(20 )*10+1*(4+1)个数;
//令百位为1,则有(2 )*100个数;
//令千位为1,则有(0 +1)*1000个数;
//以上相加,得202+205+200+1000=1607
///可以看出,有三种情况需要考虑:该位上数字小于1,等于1,大于1
#include <iostream>
#include <time.h>
int NumberOf1Between1AndN(unsigned n);//原始方法,效率不行
int NumberOf1(unsigned n);
int NumberOf1Between1AndN2(unsigned n);//高效方法,非递归
bool GetNumber(const unsigned& n, unsigned ui,
unsigned* pHi, unsigned* pBe, unsigned* pLo, unsigned* pBase);
int main()
{
clock_t clockBegin, clockEnd;
unsigned ui = 88801666u;
std::cout << "计算从1到" << ui << "整数中1出现的次数" <<std::endl;
std::cout << "begin:" << std::endl;
clockBegin = clock();
std::cout << NumberOf1Between1AndN(ui);
clockEnd = clock();
std::cout << ", used " << clockEnd - clockBegin << "ms" << std::endl;
std::cout << NumberOf1Between1AndN2(ui);
std::cout << ", used " << clock() - clockEnd << "ms" << std::endl;
system("pause");
return 0;
}
//原始方法,效率不行
int NumberOf1Between1AndN(unsigned n)
{
int number = 0;
for (unsigned i = 1; i <= n; ++i)
{
number += NumberOf1(i);
}
return number;
}
int NumberOf1(unsigned n)
{
int number = 0;
while (n)
{
if (1 == n % 10)
{
++number;
}
n /= 10;
}
return number;
}
//高效方法,非递归
int NumberOf1Between1AndN2(unsigned n)
{
int number = 0;
unsigned hi = 0, be = 0, lo = 0;
unsigned uiBase = 1;
for (unsigned i = 1, ii = 1; ii < n * 10; ++i, ii *= 10)
{
if (GetNumber(n, i, &hi, &be, &lo, &uiBase))
{
if (be > 1)
number += (hi + 1) * uiBase;
else if (be < 1)
number += hi * uiBase;
else
number += hi * uiBase + (lo + 1);
}
}
return number;
}
bool GetNumber(const unsigned& n, unsigned ui,
unsigned* pHi, unsigned* pBe, unsigned* pLo, unsigned* pBase)
{
if (0 == ui)
return false;
unsigned uiBase = 1;
while (--ui)
uiBase *= 10;
*pHi = n / (uiBase * 10);
*pBe = n % (uiBase * 10);
*pLo = *pBe % uiBase;
*pBe = *pBe / uiBase;
*pBase = uiBase;
return true;
}
/*输出:
计算从1到88886666整数中1出现的次数
begin:
72345037, used 9024ms
72345037, used 1ms
请按任意键继续. . .
*/