昨天看到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 内存