【问题标题】:speed up straightforward solution using dynamic programming使用动态编程加速直接解决方案
【发布时间】:2021-10-16 08:47:43
【问题描述】:

我最近遇到了以下问题: 我们考虑以下数组:

A = [2, 3, 6, 1, 6, 4, 12, 24]

我们需要计算这两个条件在数组中被满足的次数:

A[i] * A[j] * A[k] = A[l] so that 0 <= i < j < k < l < len(A)

对于这个例子,结果应该是 8。 数组内满足条件的示例:

2 * 3 * 1 = 6
2 * 6 * 1 = 12
6 * 1 * 4 = 24
3 * 1 * 4 = 12

我使用 python 创建的简单解决方案:

A = [2, 3, 6, 1, 6, 4, 12, 24]
result = 0
for i in range(len(A)):
    for j in range(i + 1, len(A)):
        for k in range(j + 1, len(A)):
            for l in range(k + 1, len(A)):
                if A[i] * A[j] * A[k] == A[l]:
                    result += 1
print(result)

我需要找到一种使用动态(可能是记忆化或预计算)来加速程序的方法。

result = 0
for i in range(A):
    for j in range(i + 1, A):
        for k in range(j + 1, A):
             #TODO
print(result)

我正在考虑创建一个字典,其中包含每个数字的一​​组字典,以指示数字及其位置,例如:

memo = {
    6: {
        2: True
        4: True
    }, 
    1: {
       3: True
    },
    ...
}

然后我们检查如下:

result = 0
for i in range(A):
    for j in range(i + 1, A):
        for k in range(j + 1, A):
            x = A[i] * A[j] * A[k]
            if x in memo:
                result += len([z[0] for z in memo[x].items() if z[0] > k])

这样我们将一次计算索引 k 之后相同数字的所有出现次数,我们不必遍历所有数组。

如果我的优化有缺陷,请告诉我,如果使用动态编程技术(例如记忆化或预计算)有更好的优化。

【问题讨论】:

    标签: python algorithm dynamic memoization


    【解决方案1】:

    我不是优化或动态规划方面的专家。但是你可以做些什么来加速你的代码是使用itertools.combinations 来预先确定所有索引组合。这样,您之后只需遍历所有组合即可。

    下面的代码应该更快:

    import itertools
    
    # Determine combinations of indices
    comb = itertools.combinations(range(len(A)),4)
    result = 0
    for idx in comb:
        if A[idx[0]]*A[idx[1]]*A[idx[2]] == A[idx[3]]:
            result += 1
    result
    

    如果A 的尺寸很大,这显然不是一个快速的解决方案。但是对于您的阵列,它的速度要快 2 倍

    【讨论】:

      【解决方案2】:

      一方面,似乎我们可以通过散列所有对倍数和所有对除法来获得 O(n^2 log n),其中除法是整数。对于倍数,仅存储每个此类对的较高索引的列表;对于除法,仅存储每个此类对的较低索引的列表。然后遍历每个除法对,并使用二分查找来确定有多少对倍数匹配,谁的高索引较低。

      A[i] * A[j] = A[l] / A[k]
      

      【讨论】:

        猜你喜欢
        • 2021-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 1970-01-01
        相关资源
        最近更新 更多