九章算法面试题52 数数字

九章算法官网-原文网址

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))

时间: 2024-08-07 10:57:50

九章算法面试题52 数数字的相关文章

九章算法面试题43 直方图内最大矩阵

九章算法官网-原文网址 http://www.jiuzhang.com/problem/43/ 题目 给出一个直方图(如图所示),求出所给直方图中所包含的最大矩阵面积.直方图可以用一个整数数组表示,如上图为[2, 1, 5, 6, 2, 3].每个直方块的宽度均为1.上图中包含的最大矩阵面积为10. 解答 如果对于每个直方块,找到从它开始往左边数第一个比它小的,和往右边数第一个比他小的,则可以确定出以该直方块为最矮一块的矩阵的最大面积.使用数据结构栈,栈中保存递增序列,从左到右依次遍历每个数让其

九章算法面试题31 子数组的最大差

九章算法官网-原文网址 http://www.jiuzhang.com/problem/31/ 题目 给定一个数组,求两个不相交的并且是连续的子数组A和B(位置连续),满足|sum(A) - sum(B)|最大(和之差的绝对值).例如[2, -1, -2, 1, -4, 2, 8],可以得到A=[-1, -2, 1, -4], B=[2, 8],最大差为16. 解答 预处理每个位置往左/右的最大/最小子数组,然后再枚举划分位置,求得所有MaxLeft[i] - MinRight[i+1]和Max

九章算法面试题37 主元素

九章算法官网-原文网址 http://www.jiuzhang.com/problem/37/ 题目 主元素(Majority Number)定义为数组中出现次数严格超过一半的数.找到这个数.要求使用O(1)的额外空间和O(n)的时间. 进阶1:如果数组中存在且只存在一个出现次数严格超过1/3的数,找到这个数.要求使用O(1)的额外空间和O(n)的时间. 进阶2:如果数组中存在且只存在一个出现次数严格超过1/k的数,找到这个数.要求使用O(k)的额外空间和O(n)的时间 解答 采用抵消法.一旦发

九章算法面试题40 不用除法求积

九章算法官网-原文网址 http://www.jiuzhang.com/problem/40/ 题目 给定一个数组A[1..n],求数组B[1..n],使得B[i] = A[1] * A[2] .. * A[i-1] * A[i+1] .. * A[n].要求不要使用除法,且在O(n)的时间内完成,使用O(1)的额外空间(不包含B数组所占空间). 解答 计算前缀乘积Prefix[i] = A[1] * A[2] .. A[i],计算后缀乘积Suffix[i] = A[i] * A[i+1] ..

九章算法面试题50 队列上实现Min函数

九章算法官网-原文网址 http://www.jiuzhang.com/problem/50/ 题目 ?在<九章算法面试题23 栈上实现Min函数>中,我们介绍了在栈上实现一个O(1)的Min方法.那么,如何在队列上实现一个Min方法? 要求,队列除了支持基本的Push(x) Pop()的方法以外,还需要支持Min方法,返回当前队列中的最小元素.每个方法的均摊复杂度为O(1) 解答 在九章面试题49<用栈实现队列>和面试题23<栈上实现Min函数>中,我们讲解到了如何用

九章算法面试题64 找第k大的特殊数

九章算法官网-原文网址 http://www.jiuzhang.com/problem/65/ 题目 有一种特殊的数,它的素数因子只有可能是3,5,7,不可能是其他的素数, 我们把这种数从小到大排序,得到3,5, 7, 9, 15 ... 现在我们要求其中第K大得数是多少,比如其中第4大的数是9. 在线测试本题 http://lintcode.com/en/problem/kth-prime-number/ 解答 我们所要求的元素如果除以3,5,7然后排序过后可以分成为三类元素. a. 1×3,

九章算法面试题42 构造MaxTree

九章算法官网-原文网址 http://www.jiuzhang.com/problem/42/ 题目 给定一个没有重复元素的数组A,定义A上的MaxTree如下:MaxTree的根节点为A中最大的数,根节点的左子树为数组中最大数左边部分的MaxTree,右子树为数组中最大数右边部分的MaxTree.请根据给定的数组A,设计一个算法构造这个数组的MaxTree. 解答 如果能够确定每个节点的父亲节点,则可以构造出整棵树.找出每个数往左数第一个比他大的数和往右数第一个比他大的数,两者中较小的数即为该

九章算法面试题35 构造最大数

九章算法官网-原文网址 http://www.jiuzhang.com/problem/35/ 题目 给定一个只包含正整数的数组,给出一个方法,将数组中的数拼接起来,使得拼接后的数最大.例如,[1, 32, 212]拼接之后,所得到的最大数为322121. 解答 方法一: 这道题的关键在于怎么确定每个数在最后结果中的排列位置,大家第一步想到的是肯定是第一位数越大的越靠前,如8在6, 5之前:如果第一位相同的情况出现那么再看第二位,比如下面这个例子[4,45,40]中, 45应当在40之前:难点是

九章算法面试题38 洗牌的技巧

九章算法官网-原文网址 http://www.jiuzhang.com/problem/38/ 题目 有一副扑克有2n张牌,用1,2,..2*n代表每一张牌,一次洗牌会把牌分成两堆,1,2..n和n+1...2n.然后再交叉的洗在一起:n+1, 1, n+2, 2, - n, 2n.问按照这种技巧洗牌,洗多少次能够洗回扑克最初的状态:1,2,...2n. 解答 以1 2 3 4 5 6为例,洗一次之后为4 1 5 2 6 3 .将两排数组对比看: 1 2 3 4 5 6 4 1 5 2 6 3