如何有效地找出低于阈值的最大值?

时间:2019-02-13 14:27:53

标签: python algorithm recursion divide-and-conquer

我有两个列表。列表L1包含所有正整数,列表L2包含正数(e.g. 0.01,0.1,0.5,3,5,10,100....)

给出一个小的正数M (e.g. 0.10948472),从L1中找到a,b,从c中找到L2(b/a)*c已最大化,但仍<=M

请注意,列表L2是固定的(长度在7000左右,列表L1的长度是可变的(可以有单个元素,也可以有多达3000个元素)。

我们如何有效地设计算法来解决这个问题?我正在考虑使用列表L1上的分治法将其分为两个然后合并,但没有解决。任何人都可以有效解决吗?

更新:目前,我制定了一些效率低下但正确的解决方案:首先对“ L1”进行排序。将“ L1”分为两个块:一个块是第一个N-1元素,另一个块是最后一个元素。假设在a,b,c的前N-1个元素中找到了最好的L1,我检查是否可以在第一个块中找到a,在第二个块中找到b (仅一个元素)和一些c,从而(b/a)*c得到改善。由于我必须遍历L2中的每个元素,尽管它是nlogn,但看起来仍然很慢

3 个答案:

答案 0 :(得分:1)

这个问题是3SUM-hard,所以您不可能做得比Theta(n ^ 2)好得多。如果我理解正确,您当前的算法是O(n ^ 2 log n),这没有太多改进的余地。

答案 1 :(得分:1)

根据我的理解,对于给定的a / b组合,您不必遍历L2的每个元素。按升序对L2进行排序。然后假设您从L1中选择a / b的第一个组合。对于c,您可以选择L2中间的元素,即索引3500,然后乘以a / b。如果答案小于M,则可以选择索引较高的元素,例如7000 * 3/4(即5250)。如果答案仍然较小,则将索引更高。如果(a / b)* c超过M,则选择一个较低的索引。您可以收敛到该特定a / b组合的c的最大值。

P.S。不用说,在对L1和L2进行排序之后,您可以添加一个if语句以消除L1或L2中对于任何L2或L1值分别总是超过M的那些元素。

答案 2 :(得分:0)

将L1升序排列。假设| L1 | = n。这是O(n log n)。

对于L2中的每个元素(等式中的'c'),执行以下操作(因为L2是固定的,所以为O(1)次)。

1. For the first element in L1 (which we'll treat as the 'a' in the equation), use binary search on L1 to find a second element (the 'b') s.t. (b/a)*c is maximized but still <=M.
2. Now, we'll move on to the next element in L1. Note that we're increasing the denominator, so the numerator will either stay the same or increase. We'll just iterate rather than using binary search.
3. repeat step 2.

在第2步和第3步中,我们跟踪迄今为止为a,b和c找到的最佳值。

运行时间:O(n log n)进行排序,然后在步骤2中,我们仅从每个值中增加一次分子或分母,因此这是O(n)+ O(n)= O(n)。

这利用了固定L2的优势。如果| L2 | = m且m不固定,则将为O(n log n)+ O(m * n)