从有序的指数序列生成项目

时间:2018-04-02 17:20:12

标签: math sequences

我正在为以下问题编写解决方案。

  

A是包含所有元素的列表2 ^ I * 3 ^ Q其中I和Q是按升序排列的整数。

     

写一个函数f,使得:

     

f(N)返回A [N]

前几个要素是:

A [0] = 1

A [1] = 2

A [2] = 3

A [3] = 4

A [4] = 6

A [5] = 8

A [6] = 9

A [7] = 12

我的解决方案是通过每次15次双循环生成包含前225个元素的列表,然后对此列表进行排序并返回A [N]

有没有办法在不先创建和排序列表的情况下生成此序列的第N个元素?

1 个答案:

答案 0 :(得分:0)

以下两种方法可以在不创建如此大的列表的情况下解决您的问题。每种方法都有其缺点。

首先,您可以将计数器设置为0.然后从1开始扫描所有整数。对于每个整数,在其分解中除去2和3的所有倍数。如果1仍然存在,则递增计数器;否则,保持柜台不变。当计数器达到N时,您已找到A[N]的值。例如,你增加整数1,2,3和4的计数器,但不增加5.这种方法使用非常少的内存,但需要很长时间。

第二方法使用最小优先级队列,例如Python heapq。再次,将计数器设置为零,但也初始化优先级队列以仅保持数字1,并注意到目前为止看到的最高功率3也是1.递增计数器然后查看队列中的最小数字。如果计数器为N,则您的价值为A[N]。否则,弹出该最小值并立即将其值加倍。 (pop和push可以在许多优先级队列中的一个操作中完成。)如果该值是迄今为止看到的3的最高功率,也是它的值的三倍,并注意这个新值现在是3的最高功率

第二种方法使用一个占用一些内存的优先级队列,但最大的大小只会是N的平方根。我希望时间大致等于你对大型清单的排序,但我不确定。这种方法具有最复杂的代码,并且要求您具有最小优先级队列。

您的算法具有简单的优点和大型列表的缺点。实际上,给定N,2和3的最大幂是不明显的,因此您需要使列表比需要的大得多。例如,您通过双循环计算"前225个元素的情况,每个元素15次"实际上只能达到N = 82。

下面我有三种方法的Python代码。使用timeit N=200我得到了这些时间:

1.19 ms  for sorting a long list (your approach) (powerof2=powerof3=30)
8.44 s   for factoring increasing integers
88 µs    for the min priority queue (maximum size of the queue was 17)

优先级队列大幅增加 - 远远超出我的预期。以下是所有三种方法的Python 3.6.4代码:

"""A is a list containing all elements 2^I * 3^Q where I and Q are
integers in an ascending order. Write a function f such that
f(N) returns A[N].

Do this without actually building the list A.

Based on the question <https://stackoverflow.com/questions/49615681/
generating-an-item-from-an-ordered-sequence-of-exponentials>
"""
import heapq  # min priority queue

def ordered_exponential_0(N, powerof2, powerof3):
    """Return the Nth (zero-based) product of powers of 2 and 3.
    This uses the questioner's algorithm
    """
    A = [2**p2 * 3**p3 for p2 in range(powerof2) for p3 in range(powerof3)]
    A.sort()
    return A[N]

def ordered_exponential_1(N):
    """Return the Nth (zero-based) product of powers of 2 and 3.
    This uses the algorithm of factoring increasing integers.
    """
    i = 0
    result = 1
    while i < N:
        result += 1
        num = result
        while num % 2 == 0:
            num //= 2
        while num % 3 == 0:
            num //= 3
        if num == 1:
            i += 1
    return result

def ordered_exponential_2(N):
    """Return the Nth (zero-based) product of powers of 2 and 3.
    This uses the algorithm using a priority queue.
    """
    i = 0
    powerproducts = [1]  # initialize min priority queue to only 1
    highestpowerof3 = 1
    while i < N:
        powerproduct = powerproducts[0]  # next product of powers of 2 & 3
        heapq.heapreplace(powerproducts, 2 * powerproduct)
        if powerproduct == highestpowerof3:
            highestpowerof3 *= 3
            heapq.heappush(powerproducts, highestpowerof3)
        i += 1
    return powerproducts[0]