Reducción de la complejidad del tiempo / espacio. Concurso de programación [cerrado]

I found next programming problem at one of skills testing systems :

A positive integer N is given. Consider the sequence of numbers [0, 1, ..., N]. What is the total number of zeros in the decimal representations of these numbers?

N can be very large. Hence, it is given in the form of a non-empty string S of length L, containing a decimal representation of N. S contains no leading zeros.

Escribe una función:

int number_of_zeros(char *S); 


int number_of_zeros(const string &S); 

that, given a string S, which is a decimal representation of some positive integer N, returns the total number of zeros in the decimal representations of numbers [0, 1, ..., N]. If the result exceeds 1,410,000,016, the function should return the remainder from the division of the result by 1,410,000,017.

For example, for S="100" the function should return 12 and for S="219" it should return 42.

Asumir que:

    * L is an integer within the range [1..10,000];
    * string S consists only of digits (0-9);
    * string S contains no leading zeros.

Complejidad:

    * expected worst-case time complexity is O(L);
    * expected worst-case space complexity is O(L) (not counting the storage required for input arguments).

I tried to solve it and wrote the function but the running time complexity is more sophisticated than O(L) in my solution, Can anyone solve it ( at least provide an algorithm or pseudocode or explanation )?

Good success!

preguntado el 08 de noviembre de 11 a las 12:11

How would you solve this problem by hand, without a computer? I'm pretty sure that if you try to do so you will quickly stumble on some patterns... -

there should be a way/algorithm to compute number of zeroes from decimal number inside the input string with complexity O(L) that I am trying to find ( using % , / -+,* operations ) I guess... -

2 Respuestas

This problem is a good example of the strengths of recursion. Consider the simple base case: The numbers from 1 to 1 have exactly 0 zeroes.

When you have the numbers of zeroes in the numbers from 1 to N (say x), you can compute the numbers from 1 to N*10 as 9*x+log10(N*10). The argument is simple: You need nine blocks with an equal number of zeros for the numbers 1..., 2..., 3... and the number N*10 is written as 10000... .

This recursion is valid for all powers of 10. The recursion for arbitrary N is not much harder to compute when you split the number into the powers of 10 constituting it.

respondido 08 nov., 11:17

Thank thiton for your reply. Sorry I did not understand that "When you have the numbers of zeroes in the numbers from 1 to N (say x), you can compute the numbers from 1 to N*10 as 9*x+log10(N*10). The argument is simple: You need nine blocks with an equal number of zeros for the numbers 1..., 2..., 3... and the number N*10 is written as 10000... ." can you illustrate by code or drawing.Thanks. - St Sht

Since there's only an upper limit of 10000, and this is technically a time-space complexity reduction contest just pre-compute all the possible answers in your submission code. You might notice this is very memory inefficient but with an observation that there is never a situation where any lookup value is more than 9 numbers away from a 'zero' you can use a dictionary to save a large amount of memory.

zeros.py (generates the actual code, albeit in linear time on 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]"

Generates this (32kb) file (in 31ms): http://paste.pocoo.org/show/504589/

Runtime ~ Amortized O(1)

Space ~ The density of zeroes for L=[0..10000] is 2621 ~ 26.21%. I don't think the distribution of zeros will increase greatly, but regardless - its density is definitely bounded by O(L).

respondido 08 nov., 11:18

Interesting..Do you mean to pre-compute for each N and put inside stl::map ( key : value pairs ) for example and then lookup ( search in the map ) by value ( N ) ? - St Sht

@Noxville: IIRC, most contests place a restrictive limit on your file length. - hugomg

@missingno: 32k is almost always within this limit. I have submitted a 3.4 meg file as a submission before. - Noxville

@StSht: It's essentially that, but better. Not every number increases the "zero-count", so you only store ones where there is a change. Then, if you need to lookup some query Q, you look to see if Q is in the dictionary (hashmap): if it is, you return the value, if it isn't, you decrease Q by 1 and try again. - Noxville

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.