我有两个列表。列表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,但看起来仍然很慢
答案 0 :(得分:1)
这个问题是3SUM-hard,所以您不可能做得比Theta(n ^ 2)好得多。如果我理解正确,您当前的算法是O(n ^ 2 log n),这没有太多改进的余地。
答案 1 :(得分:1)
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)