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

Math 从有序的指数序列生成项,math,sequences,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个元素的列表,然后对该列表进行排序并返回[N] 有没有办法在不首先创建和排序列表的情况下生成此序列的第N个元素?这里有两种方法可以在不创建如此大的列表的情况下解决您的问题。每种方法都

我正在为下面的问题写一个解决方案

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个元素的列表,然后对该列表进行排序并返回[N]


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

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

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

second方法使用最小优先级队列,如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]
A是一个包含所有元素2^I*3^Q的列表,其中I和Q是 升序整数。写一个函数f,使 f(N)返回一个[N]。 在不实际构建列表A的情况下执行此操作。 基于这个问题 """ 导入heapq#最小优先级队列 def有序指数(N,幂2,幂3): “”“返回2和3的幂的第n个(从零开始)乘积。 这使用了提问者的算法 """ A=[2**p2*3**p3表示p2在范围内(powerof2)表示p3在范围内(powerof3)] A.排序() 返回A[N] def有序指数_1(N): “”“返回2和3的幂的第n个(从零开始)乘积。 这使用了递增整数的因式分解算法。 """ i=0 结果=1 而i您希望使用哪种语言?它能有多大?除了不创建(和排序)列表之外,还有其他要求吗?例如,是否允许对多个数字进行因式分解?使用优先级队列在任何时候都只包含这些元素的一小部分怎么样?对于这个问题,N被限制为前200个元素。主要要求是,解决方案不会在每次运行代码时生成并保存所有200个元素。如果
N
可以与
200
一样大,则原始方法需要更大的列表。要获得
N=200
的正确答案,您需要进行从0到23的2次幂和从0到15的3次幂运算。