码迷,mamicode.com
首页 > 编程语言 > 详细

九章算法面试题52 数数字

时间:2015-05-13 10:31:23      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:数论   leetcode   九章算法   lintcode   面试题   

九章算法官网-原文网址

http://www.jiuzhang.com/problem/52/


题目

数一数在0到n之间有多少个数字k(0<=k<=9)。如n=12时,[0,1,2...,12]之间一共有5个1。分别包含在[1, 10, 11, 12]之中。


在线测试本题

http://lintcode.com/problem/digit-counts/


解答

本题的解法要诀在于熟练的使用递归思路和预处理。

预处理:
f[0] 代表了0-9中有多少个数字k。(肯定=1)
f[1] 代表了00-99中有多少个数字k。
f[2] 代表了000-999中有多少个数字k。
...
存在公式:f[i] = f[i-1] * 9 + 10i

g[1] 代表了10-99中有多少个数字k。
g[2] 代表了100-999有多少个数字k。
存在公式:g[i] = f[i] - f[i-1]          // if k != 0
                        = f[i] - f[i-1] - 10i  // if k ==0

令[a, b]代表a-b之间有多少个数字k。假设n=2345。
[0, 2345] = [0, 999] + [1000, 1999] + [2000, 2345]
这里[0, 999] = [0,9] + [10, 99] + [100, 999] = 1 + g[1] + g[2]
[1000, 1999] = [000, 999] = f[2]            // k != 1
                        [000, 999] + 1000 = f[2] + 1000 // k == 1

[2000,2345] = [000, 345]             // k!=2
                    = [000, 345] + 346   // k==2

[000,345] = [000, 099] + [100, 199] + [200, 299] + [300, 345]
= f[1] + 100 * (k==0) + f[1] + 100 * (k == 1) + f[1] + 100 * (k == 2) + [00,45] + 46 * (k == 3)

根据上面的分析,我们每次可以用O(1)的时间将带计算的n的位数减小一位:
从计算[0, 2345]到计算[000,345]到计算[00,45]。

因此整个算法的时间复杂度为O(log10(n))

九章算法面试题52 数数字

标签:数论   leetcode   九章算法   lintcode   面试题   

原文地址:http://blog.csdn.net/jiuzhang_ninechapter/article/details/45680605

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!