Find the kth eleven-non-free number

前端 未结 8 2143
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-04 10:10

Let\'s define eleven-non-free numbers:

If we consider a number as a string, then if any substring inside is a (non-zero) power of 11, then this

8条回答
  •  情深已故
    2021-02-04 10:36

    Edit: This approach misses the eleven-non-free number 1011 for example. I know what's wrong and will fix it, but can't do it now.

    Let's take a principled approach that builds up to the solution rather than trying to handle it all at once.

    Let S be the sequence of powers of 11:

    11, 121, 1331, 14641, 161051, ...

    Let E(n) be the set of numbers that contain the string representation of n as a substring. The set you are looking for is the union of E(n) over n in S.

    How do we generate the elements of E(n) for some n? (Let's take n = 121 for example.)

    Make a directed acyclic graph where n is the root node. Make n point to all 19 of the following numbers:

    Append 0-9: n0 n1 n2 n3 n4 n5 n6 n7 n8 n9
    Prepend 1-9: 1n 2n 3n 4n 5n 6n 7n 8n 9n

    Repeat the process for each of these new nodes. Notice that certain nodes may end up with more than one parent, so you'll want to maintain a hashmap from number to node pointer. (You can get to 71217 by 121 -> 1217 -> 71217 or 121 -> 7121 -> 71217.)

    This graph has the property that, for any edge from u to v, we have u < v. This is important because it means we can generate the elements of E(n) in increasing order by doing a breadth-first generation of the graph, always expanding the unexpanded node with smallest number.

    Now merge these graphs for all n in S.

    You have one large directed acyclic graph (that is infinite) that you can generate in a breadth-first manner, always expanding the unexpanded node with smallest number, emitting the next (kth) eleven-non-free number.

    Pseudocode

    It works, I tested it. Here's a C# gist: https://gist.github.com/timothy-shields/8026924

    procedure generate_eleven_non_free
    i = 1
    n = 11^i
    //frontier nodes; F.insert(x) does nothing if x already in F
    F = empty-min-heap-set
    while (true)
    {
        if (F.empty() or F.min() > n)
        {
            F.insert(n)
            i = i + 1
            n = 11^i
        }
        else
        {
            m = F.extractmin()
            yield m
            for j = 0:9        
                F.insert(append(m,j))
            for j = 1:9
                F.insert(append(j,m))
        }
    }
    

    To get the kth eleven-non-free number, simply do something like generate_eleven_non_free().element_at(k), where this is supposed to pick out the kth yielded number.

提交回复
热议问题