在csdn上面看到的题目

原创 2006年05月17日 08:05:00
csdn上面看到一道题目:
对于任意正整数nfn)表示从1n中数字1出现的次数。例如f(3)=1;   f(11)=4;   f(13)=6;
设计一个算法来计算f(n);
最开始想到的算法是最直接的算法:对1n的每个数字m,将m转换成字符串,计算该字符串中字符‘1’出现的次数。所有的次数的和就是计算的结果。具体算法如下:
 
public long countAppearTimes(long n)
{
long appearTimes = 0;
for long i = 1; i <= n; i++
{
   String strN = String.valueOf(i);
   int length = strN.length();
   for (int i=0; i< length; i++)
   {
        if (strN.charAt(i) == ‘1’)
        {
           appearTimes = appearTimes + 1;
        }
   }
}
return appearTimes;
}
这个算法比较直接,也比较好理解,但是效率太低下。当n比较小的时候还显示不出来,但是当n比较大的时候,就十分明显了。在我的机器上,当n999999999时,运行了540047ms,也就是9分钟的时间。
      是否有比较简单、高效的算法呢?
我们来做一下转换。假设给出的n是一个m位的数字,可以表示为
a1a2a3a4a5a6......am。那么将从1n的所有的数字都按m位编写,不足的在左端补0。具体形式如下
0         0          0         0      ......     0           0          1
0         0          0         0      ......     0           0          2
......
0         0          0         0      ......     0           1          0
0         0          0         0      ......     0           1          1
......
a1     a2     a3         a4     。。。。。。         am2         am-1                   am
我们可以发现以下的规律:
个位上的数字,每10个中就有11
十位上的数字,每100个中有101;(10——19
百位上的数字,每1000个中有1001;(100——199
依次类推,在从前向后数的第i位上的数字,每10m-i+1个中就有10m-i1
因此,对于n= a1a2a3a4a5a6......am;第i位的数字为ai
1.     如果ai等于0,那么第i位上有 a1a2a3a4a5a6...... ai-1 * 10 m-i1
也就是说,如果ai等于0,那么第i位上的1的个数为n/10m-i+1*10m-i1
注意,/表示整除,例如132/10 13。以下相同
例如:n13059;第三位为0。那么第三位上的1共有
13059/105-3+1*105-3=1300个。即
100——1991100——11992100——21993100——31994100——41995100——51996100——61997100——71998100——8199......13100——13199
2.     如果ai等于1,那么从1a1a2a3a4a5a6... ai-1099...9,i位上的1的个数可以根据情况1计算出来。从a1a2a3a4a5a6... ai-1100...0a1a2a3a4a5a6... ai-11 ai1 ai2... am中第i位上的1的个数为 ai1 ai2... am+1,n%10m-i + 1个。(%表示取余,例如132 %10 = 2。以下相同)所以第i位上共有n/10m-i+1*10m-i + n%10m-i + 11
3.     如果ai位是其他的数字,那么第i位上共有n/10m-i+1*10m-i + 10m-i  =(n/10m-i+1+1)* 10m-i1。具体的推算各位可以自己去验证。
根据这思想,就有以下的算法。
public long countAppearTimes(long n){
        long times = 0;
        String str = String.valueOf(n);
        int length = str.length();
        for (int i=0; i<length; i++){
//注意这里i是从0开始的,上面的算法描述中的是从1开始的,因此以下的程序稍有不同。
            long exp = Math.round(Math.pow(10, length-i-1));
            long mod = n % exp;
            long div = n / exp;
            long tempTimes = 0;
          
            if (str.charAt(i)=='1'){
                tempTimes = mod + 1;
                tempTimes = tempTimes + (div -1) * exp / 10;
                times = times + tempTimes;
            }
            else{
                if (str.charAt(i) == '0')
                    tempTimes = tempTimes + div / 10 * exp;
                else
                    tempTimes = tempTimes + (div /10 +1)*exp;
                times = times + tempTimes;
            }
        }
        return times;
    }
通过验证,这个算法和最原始的算法的结果是完全相同的(验证了从199999999)。
这个算法的效率如何呢?当n999999999时,运行了109ms

[2033]人见人爱A+B HDU(水题)

人见人爱A+B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...
  • jiangyongy
  • jiangyongy
  • 2014年09月11日 20:11
  • 608

在CSDN上看到的一些好东西,分享一…

引言     软件开发之路是充满荆棘与挑战之路,也是充满希望之路。Java学习也是如此,没有捷径可走。梦想像《天龙八部》中虚竹一样被无崖子醍醐灌顶而轻松获得一甲子功力,是很不现实的。每天仰天大叫"天神...
  • dongfangbubai1
  • dongfangbubai1
  • 2013年08月05日 09:06
  • 486

鸽兔(鸡兔)同笼不用循环

鸽兔(鸡兔)同笼不用循环 题目描述 童心未泯的redraiment经常带些碎面包什么的去广场喂鸽子和兔子,并和它们玩耍。一点也不像大学生,还是一副老不正经的样子,呵呵。 随着鸽子和兔子数...
  • huxiansheng__
  • huxiansheng__
  • 2018年01月02日 20:21
  • 21

2033 人见人爱A+B

人见人爱A+B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To...
  • liuke19950717
  • liuke19950717
  • 2015年08月08日 00:04
  • 325

我为什么要用CSDN博客?

在今年的二月份,因老师说由于学习需要,我怀着抵触的情绪开通了之前闻所未闻的CSDN博客。        三月六号我发了第一篇原创文章,说实话感觉没什么意思,只是在完成老师留给的任务。接下来的几周一直按...
  • vcx08
  • vcx08
  • 2016年05月22日 19:34
  • 430

我很优秀,但是我需要做到是让所有人看到

话题出现在一个朋友身上,他在编程方面非常优秀。不管是对于软件架构、技术把控方面都非常优异,但是却得不到领导的关注和表彰,为什么?在软件开发领域里想要有更好的发展,到底需要怎样做,仅仅技术好够吗?   ...
  • lfsf802
  • lfsf802
  • 2014年01月25日 21:29
  • 1694

如何查看CSDN 排名

CSDN默认只显示前20000名的排名,如何才能看到20000名后的排名呢?
  • psp0001060
  • psp0001060
  • 2016年08月20日 09:21
  • 1992

如何手机访问电脑服务器上的网页?

如何wifi环境下手机访问电脑wampServer或者tomcat服务器上的网页?   首先开启PHP(tomcat)服务器。 然后,几个概念: localhost是本地地址。 ht...
  • cometwo
  • cometwo
  • 2016年02月19日 09:01
  • 3861

CSDN发表博文十大注意事项

看了很多同学的作业,有待改进的地方很多;人生无处不在学习,如果我们能够做到“两人行,必有我师”的心态。发表博文,不仅仅是为了完成作业,更重要的是建立一个对外展示的窗口,让他人见博文,知其人;高质量的博...
  • dingyouzhuan0221
  • dingyouzhuan0221
  • 2014年04月14日 13:00
  • 1350

找工作期间看到的一些题目及解答

示波器:oscilloscope (OSC) 万用表:multimeter
  • cuiweitju
  • cuiweitju
  • 2014年08月22日 09:56
  • 511
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在csdn上面看到的题目
举报原因:
原因补充:

(最多只允许输入30个字)