统计1到n之间的所有数字中1出现的个数
来源:互联网 发布:淘宝运营教学视频 编辑:程序博客网 时间:2024/05/16 18:40
实现函数int func(unsigned n),其中n为正整数,返回从1到n(包含1和n)之间出现的1的个数,如
func(13)=6,func(9)=1。(注意:不能将整数转化为字符串)
这是网上以为兄弟的分析:
分析:
对于数n,可以把它分成三段,高位段most,当前位cur,低位段least,每一段分别为一个整数。对于一个有digit位的数,假设当前位是左数第i位,则设一个临时变量tmp为10的digit-i次方,即比least多一位的最小整数。如数123456,为6位数,digit=6,设当前为左起第3位,则i=3,most=12,cur=3,
least=456,tmp=1000。
如果当前位大于1,则从1到n间出现在当前位出现的1的个数是most*tmp+tmp;如果等于1,则是
most*tmp+least+1;如果小于,则为most*tmp。
实现:
int func(unsigned n)
{
int count = 0;
int digit = (int)log10(n) + 1;
int most, cur, least, tmp;
int i;
for (i=0; i<digit; ++i)
{
tmp = (int)pow(10, digit-i-1);
most = n / tmp / 10;
cur = (n / tmp) % 10;
least = n % tmp;
count += most * tmp;
if (cur > 1)
{
count += tmp;
}
else if (cur == 1)
{
count += least + 1;
}
}
return count;
}
我从新解释一下,思想都差不多:
对于一个数字中的任何第k位出现1的次数,我们将之分为两个阶段:
1. 其高位(>k的那些为,k从低位开始计数)有多大的概率使得k位出现1
2. 每次第k为出现1之后,这个1能保持多长时间。
举个例子:
n=3243,k=2,即十位上的那个数字m[k]=4
1. 显然,十位上出现1的次数是 n%100,即:如果我让十位上固定是1,然后百位和千位上数字从0增长可以增长到多少?显然,增长到32,所以,高位能使得k=2的位置上出现n%100次1,请注意:还有一次是要根据m[k]来确定的;如果m[k]>=1,则是n%100+1,否则就是n%100了。而第二位是对100mod,也就是第k位就是pow(10,k) mod n
2. 一旦第二位出现了1,能保持多长时间呢?显然,如果十位是1,那么10,11,12,。。。,19都能保持住,能保持10次。wait,是不是总是如此,不是的,如果本来第二位是大于1,当然没有问题,比如25,这个时候,10到19都小于25,所以没有问题,十位上的1出现10次;但是如果十位上是1,比如17,这样就不能出现10次了;只能出现10,11,。。。。17,也就是8次。
基于此,给出代码实现:
int func1(unsigned int n)
{
int count = 0;
int len = (int)log10((double)n);//总共多少位
int lenL = -1, lenM = -1, lenR = -1;
int idxD = -1;
while( len != -1 )
{
lenM = (int)pow(10,(double)len+1);
lenR = (int)pow(10,(double)len);
idxD = n%lenM/lenR;//高位能让该位出现几次1
count += ( n / lenM ) * lenR;
if( idxD == 1 )//当前位置上是1,要小心
count += n % lenR + 1;
else if( idxD > 1 )//大于1,直接加
count += lenR;
len--;
}
return count;
}
func(13)=6,func(9)=1。(注意:不能将整数转化为字符串)
这是网上以为兄弟的分析:
分析:
对于数n,可以把它分成三段,高位段most,当前位cur,低位段least,每一段分别为一个整数。对于一个有digit位的数,假设当前位是左数第i位,则设一个临时变量tmp为10的digit-i次方,即比least多一位的最小整数。如数123456,为6位数,digit=6,设当前为左起第3位,则i=3,most=12,cur=3,
least=456,tmp=1000。
如果当前位大于1,则从1到n间出现在当前位出现的1的个数是most*tmp+tmp;如果等于1,则是
most*tmp+least+1;如果小于,则为most*tmp。
实现:
int func(unsigned n)
{
int count = 0;
int digit = (int)log10(n) + 1;
int most, cur, least, tmp;
int i;
for (i=0; i<digit; ++i)
{
tmp = (int)pow(10, digit-i-1);
most = n / tmp / 10;
cur = (n / tmp) % 10;
least = n % tmp;
count += most * tmp;
if (cur > 1)
{
count += tmp;
}
else if (cur == 1)
{
count += least + 1;
}
}
return count;
}
我从新解释一下,思想都差不多:
对于一个数字中的任何第k位出现1的次数,我们将之分为两个阶段:
1. 其高位(>k的那些为,k从低位开始计数)有多大的概率使得k位出现1
2. 每次第k为出现1之后,这个1能保持多长时间。
举个例子:
n=3243,k=2,即十位上的那个数字m[k]=4
1. 显然,十位上出现1的次数是 n%100,即:如果我让十位上固定是1,然后百位和千位上数字从0增长可以增长到多少?显然,增长到32,所以,高位能使得k=2的位置上出现n%100次1,请注意:还有一次是要根据m[k]来确定的;如果m[k]>=1,则是n%100+1,否则就是n%100了。而第二位是对100mod,也就是第k位就是pow(10,k) mod n
2. 一旦第二位出现了1,能保持多长时间呢?显然,如果十位是1,那么10,11,12,。。。,19都能保持住,能保持10次。wait,是不是总是如此,不是的,如果本来第二位是大于1,当然没有问题,比如25,这个时候,10到19都小于25,所以没有问题,十位上的1出现10次;但是如果十位上是1,比如17,这样就不能出现10次了;只能出现10,11,。。。。17,也就是8次。
基于此,给出代码实现:
int func1(unsigned int n)
{
int count = 0;
int len = (int)log10((double)n);//总共多少位
int lenL = -1, lenM = -1, lenR = -1;
int idxD = -1;
while( len != -1 )
{
lenM = (int)pow(10,(double)len+1);
lenR = (int)pow(10,(double)len);
idxD = n%lenM/lenR;//高位能让该位出现几次1
count += ( n / lenM ) * lenR;
if( idxD == 1 )//当前位置上是1,要小心
count += n % lenR + 1;
else if( idxD > 1 )//大于1,直接加
count += lenR;
len--;
}
return count;
}
0 0
- 统计1到n之间的所有数字中1出现的个数
- 统计1到n之间的所有数字中1出现的个数
- 统计1到n之间的所有数字中1出现的个数
- 统计1到n之间的所有数字中1出现的个数
- 统计1到N之间所有数字中1的个数
- 计算1 到 N 之间 某个数字出现的个数
- 统计从1到N的所有整数中出现1的个数
- 求0到n之间所有数字中1的个数和
- 统计所有0到n之间所有含有数字1的数字和
- 统计1到n中1的出现个数
- 计算从1到n(包括n)之间出现的各位数字的个数
- 统计1到n这n个数中出现1的个数
- 统计0到n之间1的个数
- 统计0到n之间1的个数[数学]
- 统计0到n之间1的个数
- 统计0到n之间1的个数
- 统计0到n之间1的个数
- 求0到n之间出现的"1"的个数
- 程序员求职之道(《程序员面试笔试宝典》)之智力题攻略?(称重类智力题)
- 利用全注解实现ssh的一个完整例子
- 程序员求职之道(《程序员面试笔试宝典》)之程序设计基础(内存分配形式)?
- Matcher
- EL运算符
- 统计1到n之间的所有数字中1出现的个数
- 程序员求职之道(《程序员面试笔试宝典》)之海量数据处理(如何从10亿查询词找出出现频率最高的10个)?
- 程序员求职之道(《程序员面试笔试宝典》)之数据结构与算法(排序算法)?
- iOS高级面试的11个技术问题
- 程序员求职之道(《程序员面试笔试宝典》)之操作系统(内核线程和用户线程的区别)
- vim 替换 转
- csu oj 1008 Horcrux(计数)
- 我的vimrc
- 程序员求职之道(《程序员面试笔试宝典》)之操作系统(线程和进程的区别)?