如何找到总和第 k 大的对?

2024-02-13

给定两个已排序的数字数组,我们希望找到具有第 k 大可能总和的对。 (一对是第一个数组中的一个元素和第二个数组中的一个元素)。例如,对于数组

  • [2,3,5,8,13]
  • [4,8,12,16]

总和最大的对是

  • 13 + 16 = 29
  • 13 + 12 = 25
  • 8 + 16 = 24
  • 13 + 8 = 21
  • 8 + 12 = 20

因此,总和第四大的对是 (13, 8)。如何找到具有第 k 大可能和的对?

另外,最快的算法是什么?数组已排序且大小为 M 和 N。


我已经知道O(Klogk)解决方案 ,使用给定的 Max-Heaphere https://stackoverflow.com/questions/5212037/find-the-kth-largest-sum-in-two-arrays .

也是最爱之一Google面试问题,他们要求O(k) 解 .

我还在某处读到存在一个O(k)解决方案,我无法弄清楚。

有人可以用伪代码解释正确的解决方案吗?

附: 请不要发帖this http://www.ocf.berkeley.edu/~wwu/cgi-bin/yabb/YaBB.cgi?board=riddles_cs;action=display;num=1132204952;start=25#47链接作为答案/评论。它不包含答案。


我从一个简单但不完全线性时间的算法开始。我们选择一些值array1[0]+array2[0] and array1[N-1]+array2[N-1]。然后我们确定有多少对总和大于该值以及有多少对总和小于该值。这可以通过使用两个指针迭代数组来完成:当总和太大时,指向第一个数组的指针递增;当总和太小时,指向第二个数组的指针递减。对不同的值重复此过程并使用二分搜索(或单边二分搜索),我们可以在 O(N log R) 时间内找到第 K 个最大和,其中 N 是最大数组的大小,R 是之间可能值的数量array1[N-1]+array2[N-1] and array1[0]+array2[0]。仅当数组元素是由小常数限制的整数时,该算法才具有线性时间复杂度。

Previous algorithm may be improved if we stop binary search as soon as number of pair sums in binary search range decreases from O(N2) to O(N). Then we fill auxiliary array with these pair sums (this may be done with slightly modified two-pointers algorithm). And then we use quickselect algorithm to find Kth largest sum in this auxiliary array. All this does not improve worst-case complexity because we still need O(log R) binary search steps. What if we keep the quickselect part of this algorithm but (to get proper value range) we use something better than binary search?

我们可以使用以下技巧来估计值范围:从每个数组中获取每隔一个元素,并尝试找到具有排名的对和k/4对于这些半数组(递归地使用相同的算法)。显然,这应该给出所需值范围的一些近似值。事实上,这个技巧的稍微改进的变体给出了仅包含 O(N) 元素的范围。这在以下论文中得到证明:“X + Y 中的选择以及已排序行和列的矩阵”作者:A. Mirzaian 和 E. Arjomandi http://www.cse.yorku.ca/~andy/pubs/X%2BY.pdf。本文包含算法的详细解释、证明、复杂性分析以及算法所有部分的伪代码(除了快速选择 http://en.wikipedia.org/wiki/Quickselect。如果需要线性最坏情况复杂性,可以通过以下方式增强快速选择中位数的中位数 http://en.wikipedia.org/wiki/Median_of_medians算法。

该算法的复杂度为O(N)。如果其中一个数组比其他数组短 (M

如果 k N(N-1),我们最好解决相反的问题:第 k 个最小和。

我将简单的 C++11 实现上传到ideone http://ideone.com/qe1YHA。代码未优化且未经过彻底测试。我试图使其尽可能接近链接论文中的伪代码。该实现使用std::nth_element,仅允许平均线性复杂度(不是最坏情况)。


在线性时间内求第 K 个和的完全不同的方法是基于优先级队列 (PQ)。一种变体是将最大的对插入到 PQ,然后重复删除 PQ 的顶部并插入最多两对(一对在一个数组中具有递减索引,另一对在另一个数组中具有递减索引)。并采取一些措施来防止插入重复对。其他变体是插入包含第一个数组的最大元素的所有可能对,然后重复删除 PQ 的顶部,并在第一个数组中插入具有递减索引的对,并在第二个数组中插入相同索引的对。在这种情况下,无需担心重复项。

OP 提到 O(K log K) 解决方案,其中 PQ 被实现为最大堆。但在某些情况下(当数组元素是均匀分布且范围有限的整数,并且仅在平均情况下而不是最坏情况下需要线性复杂度时),我们可以使用 O(1) 时间优先级队列,例如,如本文所述:“事件驱动分子动力学模拟的复杂性 O(1) 优先级队列”作者:Gerald Paul http://arxiv.org/pdf/physics/0606226。这允许 O(K) 预期时间复杂度。

这种方法的优点是可以按排序顺序提供前 K 个元素。缺点是数组元素类型的选择有限,算法更复杂且更慢,渐近复杂度更差:O(K) > O(N)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何找到总和第 k 大的对? 的相关文章

  • 一种良好且简单的随机性测量方法

    获取一长整数序列 例如 100 000 个 并返回序列随机性的测量值的最佳算法是什么 该函数应返回单个结果 如果序列并非完全随机 则返回 0 如果完全随机 则返回 1 如果序列有点随机 它可以给出介于两者之间的东西 例如0 95 可能是一个
  • 为什么直接内存“数组”的清除速度比通常的 Java 数组慢?

    我建立了一个 JMH 基准来衡量什么会更快Arrays fill与空 System arraycopy从空数组中 将 DirectByteBuffer 归零或将unsafe内存块试图回答这个问题question https stackove
  • 如何在 JavaScript 中构建树模式匹配算法?

    好吧 这是一个有点复杂的问题 但是 tl dr 基本上是如何使用 模式树 解析 实际树 如何检查特定的树实例是否与特定的模式树匹配 首先 我们有我们的结构模式树 模式树通常可以包含以下类型的节点 sequence节点 匹配一系列项目 零个或
  • 素数生成器算法

    我一直在尝试解决素数生成算法的SPOJ问题 这是问题 彼得想为他的密码系统生成一些素数 帮助 他 你的任务是生成两个给定之间的所有素数 数字 Input 输入以单行中测试用例的数量 t 开始 t Output 对于每个测试用例 打印所有素数
  • 如何知道您的单元测试装置是否“尺寸合适”?

    您如何知道 测试夹具 的尺寸是否合适 我所说的 测试夹具 是指一个包含大量测试的类 我在测试装置中一直注意到的一件事是它们变得有点冗长 鉴于它们也可能不够详细 您如何了解单元测试的大小是否合适 我的假设是 至少在 Web 开发的背景下 您应
  • Math.random() 在 JavaScript 中如何工作?

    我最近想出了如何通过谷歌获取随机数 这让我思考如何Math random 工作 所以我在这里我无法弄清楚他们是如何做到 Math random 的 除非他们使用了类似时间的东西 有谁知道 JavaScript 是如何做到的吗 Math ra
  • 在 C 中如何安全地找到 2 个有符号整数之间的绝对差?

    绝对差是两个数字之间差的绝对值 假设我有 2int变量 x and y 我想找到绝对差异 一个简单的解决方案是 unsigned diff abs x y 然而 如果发生溢出 这些会调用未定义的行为并给出不正确的结果 例如x is INT
  • 为什么 Android Eclipse 不断刷新外部文件夹并花费很长时间?

    我只有一部新的 Android 手机 我一直在修补一些基本的应用程序 每当我保存任何内容时 Eclipse 的 Android 插件就会刷新外部文件夹 这让我抓狂 通常我不会介意 但当需要 10 秒才能刷新时 我开始注意到 我已经搜索过 其
  • 有哪些学习线程编程的好资源? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 随着多核CPU在桌面上的兴起 多线程技能将成为程序员的宝贵资产 您能为想要学习线程编程的程序员推荐一些好的资源 书籍 教程 网站等 吗 看
  • 在任意时间范围内找到最佳日/月/年间隔的算法?

    如果您有时间表 请说 March 19 2009 July 15 2011 是否有一种算法可以将该时间范围分解为 March 19 2009 March 31 2009 complete days April 1 2009 December
  • 如何将多边形放入另一个多边形内[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有两个多边形 如下图所示 左边是 粗多边形 右边是 最终多边形 现在 我正在寻找算法来将 最终多边形 拟合到 粗糙多边形 内 并具有
  • 如何有效地从 DB2 表中删除所有行

    我有一个大约有 50 万行的表 我想删除所有行 如果我做简单的delete from tbl 事务日志已满 我不关心这种情况下的事务 无论如何我都不想回滚 我可以删除许多事务中的行 但是有更好的方法吗 如何有效地从 DB2 中的表中删除所有
  • 计算二维笛卡尔坐标中不规则形状的边界

    我正在寻找一种计算不规则形状边界的解决方案 Lats take a look at Square example 如果我有Minimum x and y and Maximum x and y like MaxX 5 MinX 1 MaxY
  • 什么是“朴素”算法,什么是“封闭式”解决方案?

    我有一些关于描述算法时使用的术语语义的问题 首先 朴素 算法是什么意思 这与给定问题的其他解决方案有何不同 解决方案还可以采取哪些其他形式 其次 我听到很多人提到 封闭式 解决方案 我也不知道这意味着什么 但在尝试解决递归关系时经常会出现
  • 对于双核手机,availableProcessors() 返回 1

    我最近购买了一部 Moto Atrix 2 手机 当我尝试查看手机中的处理器规格时 Runtime getRuntime availableProcessors 返回 1 proc cpuinfo 也仅包含有关处理器 0 的信息 出于好奇
  • Java ByteBuffer 性能问题

    在处理多个千兆字节文件时 我注意到一些奇怪的事情 似乎使用文件通道从文件读取到使用 allocateDirect 分配的重用 ByteBuffer 对象比从 MappedByteBuffer 读取要慢得多 事实上它甚至比读取到字节还要慢使用
  • 解释 Vinay Deolalikar 的证明 P != NP [已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 最近有一个paper https www win tue nl gwoegi P versus NP Deolalikar pdf惠普实验
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • 如何光栅化旋转矩形(通过 setpixel 在 2d 中)

    我有四个 2d 顶点 A B C D 的旋转矩形 我需要在像素缓冲区中 有效地 光栅化 绘制它 使用 setpixel x y 颜色 怎么做 我正在尝试使用一些代码 例如 convertilg a b c d do up down left
  • 总和不小于 key 的数组的最小子集

    给定一个数组 假设为非负整数 我们需要找到最小长度子集 使得元素之和不小于 K K 是作为输入提供的另一个整数 是否有可能找到时间复杂度为 O n n 的大 oh 的解决方案 我目前的想法是这样的 我们可以在 O n log n 中对数组进

随机推荐