Algorithm 如何从两个排序数组的对中获得K个最小乘积?
给出了两个排序数组。我们必须从这些数组的对中找到K个最小乘积。我可以想到一个mnlogk解决方案,但是即使数组不是按排序的,这个解决方案也可以工作。我们能利用这个排序顺序找到更好的解决方案吗 我尝试使用大小为k的最大堆来获得mnlogk解决方案 输入:nums1=[-2,-1,0,1,2],nums2=[-3,-1,2,4,5],k=3 输出:[-10,-8,-6]Algorithm 如何从两个排序数组的对中获得K个最小乘积?,algorithm,Algorithm,给出了两个排序数组。我们必须从这些数组的对中找到K个最小乘积。我可以想到一个mnlogk解决方案,但是即使数组不是按排序的,这个解决方案也可以工作。我们能利用这个排序顺序找到更好的解决方案吗 我尝试使用大小为k的最大堆来获得mnlogk解决方案 输入:nums1=[-2,-1,0,1,2],nums2=[-3,-1,2,4,5],k=3 输出:[-10,-8,-6] 说明:-2*5、-2*4、2*-3不要使用堆,而是尝试按排序顺序生成产品 想象一个n*m网格,由索引形成到相应的数组中。在任何给定
说明:-2*5、-2*4、2*-3不要使用堆,而是尝试按排序顺序生成产品 想象一个
n*m
网格,由索引形成到相应的数组中。在任何给定的时间点,网格被划分为“已检查”和“尚未检查”部分。我们将保持一个不变量,即每对被检验的产品小于未被检验产品的产品。难点在于证明它们之间的边界有O(n+m)
对;数组被排序这一事实对于证明是至关重要的
现在,您可以沿着边界测试产品,获取最小值,并相应地修改边界。此操作将花费O(n+m)
时间,并将执行k次。总体复杂性是O(k(n+m)
)
最后的优化:上面的计划一次又一次地重新计算边界沿线的许多产品。将边界表示为排序映射可能会将复杂性降低到O(klog(n+m))这里有一个具有O(kmin(n,m))时间复杂性的算法 设A和B为整数列表排序,即A=[a1 a2 a3…am]带ai≤ ai+1,B=[b1 b2 b3…bn]和bi≤ bi+1 现在假设ai≥ 0和bi≥ 0下面我们将演示如何计算负整数 设p=(i j)是一对,其中i和j是ai和bj的索引。设P是一个对的列表。集合P=[(11)(12)(13)…(1n)]。假设k>0(和k≤ m x n)。设R是k个第一乘积对的列表。初始化R=[]
(1 1):2
被添加到R中,p中的第一对成为(1+1)
在下一次迭代中,(21):6
被添加到R中,p中的第一对成为(2+11)
。因为该对的乘积大于P中下一对的乘积,所以它们被交换
R = [(1 1):2 (2 1):6]
P = [(3 1):13 (1 2):12 (1 3):18]
P = [(1 2):12 (3 1):13 (1 3):18]
下一次迭代,类似于上一次迭代的操作
R = [(1 1):2 (2 1):6 (1 2):12]
P = [(2 2):36 (3 1):13 (1 3):18]
P = [(3 1):13 (1 3):18 (2 2):36]
在这个迭代中,将(3 1):13
添加到R之后,第一对p变为(3+1)
,但该对不存在。所以,它只是从P中删除
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13]
P = [(1 3):18 (2 2):36]
以下是p为空之前的所有剩余迭代
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18]
P = [(2 3):54 (2 2):36]
P = [(2 2):36 (2 3):54]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36]
P = [(3 2):78 (2 3):54]
P = [(2 3):54 (3 2):78]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54]
P = [(3 3):117 (3 2):78]
P = [(3 2):78 (3 3):117]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54 (3 2):78]
P = [(3 3):117]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54 (3 2):78 (3 3):117]
P = []
现在,如果A和B同时包含非负整数和负整数,我们可以使用上述算法同时求解最多4个子问题,以获得k个最小整数。为此,我们定义了迭代器函数F(A,B),该函数在每次调用时使用上述算法按递增顺序生成下一个乘积。设A-和A+是A的子列表,分别包含其负整数和非负整数。B-和B+也是这样。我们为以下4个子问题调用迭代器函数
F(A+, B+)
F(A+, reverse(B-))
F(reverse(A-), B+)
F(reverse(A-), reverse(B-))
其中,reverse(L)返回列表L及其元素的顺序相反。我们迭代这四个迭代器,选择k个最小的返回对 你能给出一个例子来说明这个问题吗?在你的例子中,你把第一个数组中的-2与第二个数组中的5和4配对。这是正确的吗?@Robert yes,这是解决这个问题的正确方法。(我很惊讶没有从两套产品中找到K个最大的产品,答案是否恰当。)4个子问题的识别就在现场。在循序渐进地介绍要遵循的程序时,我看不出我≠P中的1,而n开始时是B的基数,在过程中用作P中的下一对n。@greybeard捕捉得好!我修正了打字错误。谢谢我添加了一个详细的示例。@greybeard参见示例,第三次迭代,删除
(12):12
@greybeard(1+1)=(21)
,第一对的乘积变为(22):36
。我不确定你的意思。获取最小边界值会有什么帮助?我们不是每次都要取k最小值吗?我们如何修改边界?
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13]
P = [(1 3):18 (2 2):36]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18]
P = [(2 3):54 (2 2):36]
P = [(2 2):36 (2 3):54]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36]
P = [(3 2):78 (2 3):54]
P = [(2 3):54 (3 2):78]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54]
P = [(3 3):117 (3 2):78]
P = [(3 2):78 (3 3):117]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54 (3 2):78]
P = [(3 3):117]
R = [(1 1):2 (2 1):6 (1 2):12 (3 1):13 (1 3):18 (2 2):36 (2 3):54 (3 2):78 (3 3):117]
P = []
F(A+, B+)
F(A+, reverse(B-))
F(reverse(A-), B+)
F(reverse(A-), reverse(B-))