来自两个排序数组的最大对数
Posted
技术标签:
【中文标题】来自两个排序数组的最大对数【英文标题】:Maximum number of pairs from two sorted arrays 【发布时间】:2011-10-31 17:13:12 【问题描述】:这不是原始问题。我有一个复杂的问题,现在简化为:
有两个排序数组,A
和 B
,分别带有 m
和 n
元素,m = \Theta(n)
在o(mn)
时间运行的算法能否找到最大对数,使得A[i]-B[j] <= T
其中 T 是某个常数?如何才能做到这一点?
编辑:
这些对应该是不相交的,即一个元素最多只能选择一次。
算法应该在 little-o(mn) 中运行,这意味着在 mn 时间内运行的解决方案是不可接受的。
是否也可以找到我们选择的对?
澄清:
如果数组是a_1, a_2, ..., a_m
和b_1, b_2, ..., b_n
,我需要找到对(a_i, b_j)
这样|a_i - b_j| <= T
。不允许多次选择一个元素。我们如何最大化给定数组的对数?
【问题讨论】:
以前从未见过 little-O:en.wikipedia.org/wiki/…。 Wiki 说o(mn)
意味着复杂性由mn
主导,这意味着mn
时间是 可以接受的,m+n
是不 可以接受的。请澄清。
@MooingDuck:不,右边有一个 epsilon 因子 - 这意味着它必须比 mn 运行快。跨度>
@AasmundEldhuset:我重读了这篇文章。我又错了。你是对的。
@MooingDuck 你能详细说明怎么做吗?
没关系,新的说明有一个绝对值,这意味着这个页面上的每个答案(截至目前)都是不正确的。
【参考方案1】:
更新 2:
更新的问题(仅使用任一数组中的元素一次,获取对,并且值的绝对差必须低于T
)可能可以在O(n + m)中完成 时间。我还没有充分考虑下面的算法来决定它是否总是能获得最大的对数,但在大多数情况下应该:
int i = 0;
int j = 0;
while(i < A.length)
while(j < B.length)
if(A[i]-B[j] <= T)
if(A[i]-B[j] >= -1 * T)
addPair(i, j);
j++;//don't consider this value the next time
break;
j++;
i++;
【讨论】:
这可以从 B 中多次选择一个元素。此外,不能保证它会选择最大的对集合。 问题的最新更新说|a_i - b_j| <= T
,添加了一个绝对值。
@PulkitGoyal:实际上,因为 i 和 j 都不会减少,所以它永远不会多次使用 A
或 B
中的任何元素。
@MooingDuck 啊!抱歉,是我的错。但它仍然不适用于差异的绝对值。例如,考虑以下数组:20,30
和 35,70
和 T=10
。该算法不会选择任何对。但是,最好选择 (30,35)
对。
@PulkitGoyal:我想知道我怎么从来没有注意到这段代码中的错误。没错,正确的答案稍微复杂一些。【参考方案2】:
在O(n lg n) = O(m lg m)
中:从A
的元素创建平衡二叉搜索树,并在每个节点中存储元素的索引和元素值。对于B
的每个元素,搜索小于或等于B[j] + T
的最大值。这个数字的索引会告诉你有多少数字小于或等于这个数字。
【讨论】:
“创建平衡的二叉搜索树” - 这本身不需要时间吗? 我正在寻找不同的对,这意味着一个数字一旦被选中就不能再次被选中。 @GigaWatt:是的,但只有O(n lg n)
。
@AasmundEldhuset 我不明白这将如何产生正确数量的对,因为它可以多次使用一个元素。【参考方案3】:
如果您想要匹配|A[i]-B[j]| <= T
的对数,其中每个A[i]
和B[j]
在所有对中仅使用一次:
int lastB = 0;
int result=0;
for(int a = 0; a<A.size(); ++a)
const int minB = A[a] - T;
while(lastB<B.size() && B[lastB] < minB)
++lastB;
const int maxB = A[a] + T;
if (lastB<B.size() && B[lastB] > minB)
++lastB;
++result;
return result;
此算法扫描B
中的最小范围,并确保B
中的任何元素都不会被使用两次。
【讨论】:
您的解决方案总是找到我可以使用 A_max 作为第一个元素获得的最大对数。但我需要元素是不同的。这意味着一旦你从一个数组中选择了一个元素,你就不能再选择它了。 由于所有其他元素都小于A_max
,并且结果我从不返回超过A_max
,因此您会发现无论如何这都会返回正确的数字。
我看不出它如何返回正确的结果。例如考虑以下数组:1, 2, 3, 1000
和 999, 1000, 1001, 1002
以及阈值 5。如果我正确理解您的算法,它将返回对数为 4,而这里只有一对是可能的。
它将返回 4,原始问题有 4 个。 (1,999) (2,1000) (3,1001) (1000,1002) 等式是A[i]-B[j] <= T
,2-1000<=5
绝对正确。我刚刚注意到你的编辑 now 显示了一个绝对值,在这种情况下这个算法是有缺陷的。然后使用 Briguy37 的答案,它是下一个最快的。
@PulkitGoyal:在发现 Briguy37 有一个(主要)错误后,我用他的算法的固定版本替换了我的答案。以上是关于来自两个排序数组的最大对数的主要内容,如果未能解决你的问题,请参考以下文章
给定一个数组,求如果排序后,相邻两个元素的最大差值,要求时间复杂度为O(N)
2021-07-30:两个有序数组间相加和的Topk问题。给定两个有序数组arr1和arr2,再给定一个整数k,返回来自arr1和arr2的两个数相加和最大的前k个,两个数必须分别来自两个数组。按照降