我在其中一个技能测试系统中发现了下一个编程问题:
给出正整数N.考虑数字序列[0,1,...,N]。这些数字的十进制表示中的零总数是多少?
N可能非常大。因此,它以长度为L的非空字符串S的形式给出,包含N的十进制表示.S不包含前导零。
写一个函数:
int number_of_zeros(char *S);
int number_of_zeros(const string &S);
给定一个字符串S,它是某个正整数N的十进制表示,返回数字[0,1,...,N]的十进制表示中的零的总数。如果结果超过1,410,000,016,则该函数应将结果除数的余数返回1,410,000,017。
例如,对于S =“100”,函数应返回12,对于S =“219”,它应返回42。
假设:
* L is an integer within the range [1..10,000];
* string S consists only of digits (0-9);
* string S contains no leading zeros.
复杂度:
* expected worst-case time complexity is O(L);
* expected worst-case space complexity is O(L) (not counting the storage required for input arguments).
我尝试解决它并编写了函数,但运行时复杂度比我的解决方案中的O(L)更复杂, 任何人都可以解决它(至少提供算法或伪代码或解释)?
成功!
答案 0 :(得分:2)
这个问题是递归优势的一个很好的例子。考虑简单的基本情况:从1到1的数字恰好为零。
如果从1到N(比如x)的数字中有零个数,则可以将1到N * 10之间的数字计算为9 * x + log10(N * 10)。这个论点很简单:对于数字1 ...,2 ...,3 ...你需要9个具有相等数量零的块,而数字N * 10被写为10000 ....
此递归适用于10的所有幂。当您将数字拆分为构成它的10的幂时,任意N的递归并不难计算。
答案 1 :(得分:0)
由于只有10000的上限,这在技术上是一个时空复杂性减少竞赛,只需预先计算您提交代码中的所有可能答案。您可能会注意到这是非常低效的内存,但是观察到从来没有任何查找值超过9个数字的情况,您可以使用字典来节省大量内存。
zeros.py(生成实际代码,尽管是L上的线性时间):
def zeros(n):
l = str(n)
return l.count("0")
total = 0
d = {}
for i in xrange(10001):
delta = zeros(i)
if (delta>0):
total += delta
d[i] = total
print len(d)
print
print "d = " + str(d)
print "N = int( raw_input () )"
print "while (N not in d):"
print "\t N-=1"
print "print d[N]"
生成此(32kb)文件(31ms内):http://paste.pocoo.org/show/504589/
运行时〜分期付款O(1)
空间~L = [0..10000]的零密度为2621~26.21%。我不认为零的分布会大大增加,但无论如何 - 它的密度肯定受到O(L)的限制。