从给出所需系数的数字数组中查找组合

问题描述

请为此类任务推荐最佳算法或解决方案:

有几个带小数的数组

a = [1.5,2,3,4.5,7,10,...(up to 100 numbers)]
b = [5,6,8,14,...]
c = [1,4,6.25,8.15 ...] (up to 7 arrays)

数组可以是任意长度并包含不同数量的数字。

需要从每个数组中选择一个数字,使其乘积在给定的范围内。

例如,所需产品的数据应介于 40 和 50 之间。 解决方法可以是:

  1. a[2] * b[2] * c[1] = 3 * 8 * 2 = 48
  2. a[0] * b[3] * c[1] = 1.5 * 14 * 2 = 42

如果可以有多种解决方案(不同的组合),那么如何以最佳方式找到所有解决方案?

解决方法

这是可行的,但勉强可以。这将需要使用各种策略一遍又一遍地组合成对的事物。

首先,如果您有 2 个不超过 100 个事物的数组,您可以创建一个所有对的数组,按总和升序或降序排序,其中只有 10,000 个事物。

接下来,我们可以使用 heap 来实现 priority queue

使用优先级队列,我们​​可以组合 2 个最大为 10,000 的有序数组,以升序或降序输出总和,同时不跟踪超过 10,000 个事物。如何?首先我们创建一个这样的数据结构:

Create priority queue
For every entry a of array A:
    Put (a,B[0],0) into our queue using the product as a priority
return a data structure which contains B and the priority queue

现在我们可以像这样得到值:

If the priority queue is empty:
    We're done
else:
    Take the first element of the queue
    if not at the end of B:
        insert (a,b[next_index],next_index) into the queue
    return that first element

我们可以通过查看队列的第一个元素而不触及数据结构来窥视它们。

此策略可以流过 2 个大小为 10,000 的数组,总工作量只需几十亿次操作。

好的,现在我们可以安排总是有 7 个数组。 (有些可能只是一个微不足道的 [1]。)我们可以从蛮力策略开始如下。

Combine the first 2 ascending.
Combine the second 2 ascending.
Combine the third 2 descending.
Arrange the last descending.

接下来我们可以使用优先队列合并策略如下:

Combine (first 2) with (second 2) ascending
Combine (third 2) with last descending

我们现在只需要发电机。

现在我们的策略将如下所示:

For each combination (in ascending order) from first 4:
    For each combination that lands in window from last 3:
        emit final combination

但是我们如何做窗口呢?好吧,随着前 4 个组合的上升,最后 3 个必须落入的窗口下降。所以调整窗口看起来像这样:

while there is a next value and next value is large enough to fit in the window:
    Extract next value
    Add next value to end of window
while first value is too large for the window:
    remove first value from the window

(可变大小的数组,例如 Python 的 List,可以在每个摊销的 O(1) 中执行这两种操作。)

所以我们实际的完成方式是:

For each combination (in ascending order) from first 4:
    adjust entries in window from last 3
    For each in window from last 3:
        emit final combination

这具有数十亿次操作加上 O(number of answers) 来实际发出组合的固定开销。这包括许多具有大约 10k 个项目的数据结构,以及一个最大大小为 100 万个项目的窗口,最大内存使用量为几百 MB。