时间/空间复杂性降低。编程比赛

时间:2011-11-08 12:34:37

标签: algorithm stl-algorithm

我在其中一个技能测试系统中发现了下一个编程问题:

给出正整数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)更复杂, 任何人都可以解决它(至少提供算法或伪代码或解释)?

成功!

2 个答案:

答案 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)的限制。