我正在为以下问题编写解决方案。
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个元素?
答案 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]