如何有效地找出低于阈值的最大值?
Posted
技术标签:
【中文标题】如何有效地找出低于阈值的最大值?【英文标题】:How to efficiently find out the maximum value below a threshold? 【发布时间】:2019-07-07 10:14:34 【问题描述】:我有两个列表。列表L1
包含所有正整数,列表L2
包含正数(e.g. 0.01,0.1,0.5,3,5,10,100....)
。
给定一个小的正数M
(e.g. 0.10948472)
,从L1 中找到a,b
,从L2
s.t.中找到c
。 (b/a)*c
已最大化但仍为 <=M
请注意,列表 L2
是固定的(长度约为 7000
),列表 L1
的长度是可变的(可以有单个元素或最多 3000
个元素)。
我们如何有效地设计算法来解决这个问题?我正在考虑使用列表L1
上的分而治之将其分成两部分然后合并,但没有成功。任何人都可以有效地解决它?
更新:目前我制定了一些低效但正确的解决方案:首先对“L1”进行排序。将“L1”分成两个块:一个块是第一个N-1
元素,另一个块是最后一个元素。假设在L1
的第一个N-1
元素上找到了最好的a,b,c
,我检查我们是否可以在第一个块中找到一些a
,在第二个块中找到b
(仅一个元素)和一些c
,这样(b/a)*c
就会改进。由于我必须循环遍历L2
中的每个元素,虽然它是nlogn,但似乎仍然很慢
【问题讨论】:
你是不是先以低效的方式做到了? 是的,我想出了两个低效但正确的解决方案。让我更新一下这个问题,谢谢 我想这可以在O((n^2) * log(n^2))
完成,方法是创建所有可能的b/a
和d/c
的数组并对它们进行排序。您想达到什么复杂程度?
@dWinder 我正在尝试至少达到 O(nlogn)
O(nlog n) 中的 n 是什么意思?从技术上讲,您有两个不同长度的数组,从长度(L1)将它们称为n1,将长度(L2)称为n2。我相信你可以得到 O(n1*n2*log(n1)) 并且由于 n2 是固定的,技术上是 O(n*log(n)) - 但这似乎是作弊。
【参考方案1】:
这个问题是3SUM-hard,所以你不太可能比 Theta(n^2) 做得更好。如果我理解正确,您当前的算法是 O(n^2 log n),这并没有很大的改进空间。
【讨论】:
鉴于 L2 是固定的,我认为对于 n=|L2|,这是 O(n log n)。【参考方案2】:据我了解,对于给定的 a/b 组合,您不必遍历 L2 的每个元素。按升序对 L2 进行排序。然后假设您从 L1 中选择 a/b 的第一个组合。对于 c,您可以选择 L2 中间的元素,即索引 3500 并与 a/b 相乘。如果答案小于 M,您可以选择更高索引处的元素,例如 7000*3/4 即 5250。如果答案仍然更少,则继续更高。如果相反 (a/b)*c 超过 M,则选择较低的索引。对于特定的 a/b 组合,您可以收敛到 c 的最大值。
附:不用说,在对 L1 和 L2 进行排序之后,您可以添加一个 if 语句来消除 L1 或 L2 中的那些元素,对于 L2 或 L1 的任何值,它们总是会分别超过 M。
【讨论】:
【参考方案3】:对 L1 升序排序。假设 |L1| = n。这是 O(n log n)。
对于 L2 中的每个元素(等式中的“c”),执行以下操作(所以 O(1) 次,因为 L2 是固定的)。
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)
【讨论】:
嗨,戴夫,感谢您的建议。在第 2 步中,“分子要么保持不变,要么增加”:这意味着我们将从当前位置一步一步向右移动,直到找到最大值,对吗? @ADS_Auckland 是的!以上是关于如何有效地找出低于阈值的最大值?的主要内容,如果未能解决你的问题,请参考以下文章