算法:计算1的个数

昨天看到csdn上有一个关于google的面试题,题目的大致内容是,计算0~n之间的1的个数,例如n=12时,1的个数为5,为什么是5呢,大家可以计算一下 0-9有一个1,10-12有4个1。
下面是我的思路。
如果n的长度是1位,如果n>0那么结果是1,否则是0
如果n的长度大于1位,那么如果n>(n的长度位数数字的最小值*2-1),那么
f(n)=(n的最高位 * f(比n的长度小一位的最大数) + n的长度位数数字的最小值)。
否则
f(n)=(n的最高位 * f(比n的长度小一位的最大数) + n-比n的长度小一位的最大数)

下面是源代码:

public double f(double d)
  {
   const string strT = "1000000000000000000000000000";
   //判断参数d的长度
   int length = d.ToString().Length;   
   if(length == 1)
   {
    if(d>0)
    {
     return 1;
    }
    else
    {
     return 0;
    }
   }
   else
   {
    //取一个数,这个数是长度比参数d少一位的最大的数,例如如果d=2300,那么d0=1000;
    double d0 = double.Parse(strT.Substring(0,length));
    //取一个数,这个数是长度比参数d少一位的最大的数,例如如果d=2300,那么d1=999;
    double d1 = double.Parse(strT.Substring(0,length)) - 1;
    //取一个数,这个数是用来判断应该取什么值的。例如参数d的长度是两位,那么这个数就是19,如果是3为,那么是199
    double d2 = double.Parse("1"+ d1.ToString());
    //取参数的首位的数字
    int iMaxStart = int.Parse((d.ToString())[0].ToString());
    //取参数的除首位以外的其他数值
    double dOther = double.Parse(d.ToString().Substring(1,length-1));

    if(d > d2)
    {
     return ( iMaxStart * f(d1) + f(dOther) + d0);
    }
    else
    {
     return (iMaxStart * f(d1) + f(dOther) + (d - d1));
    }
   }
  }

运行结果:
1000000000000的运行时间为:156毫秒
计算f(n) =n的时间是:29.406秒
我的机器:P4 2.6  512 内存


原文地址:https://www.cnblogs.com/ami/p/455679.html