如何找到总和第 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 大的对? 的相关文章

  • 单位安全平方根

    我只是想知道如何以与 F 正确交互的方式编写用户定义的平方根函数 sqrt 单位制 http blogs msdn com andrewkennedy archive 2008 09 04 units of measure in f par
  • 为什么 System.nanoTime() 比 System.currentTimeMillis() 慢(性能)?

    今天我做了一个快速基准测试来测试速度性能System nanoTime and System currentTimeMillis long startTime System nanoTime for int i 0 i lt 1000000
  • 生成所有多集大小为 n 的分区的算法

    我一直在试图找出一种方法来生成多重集的所有不同的大小为 n 的分区 但到目前为止却空手而归 首先让我展示一下我想要实现的目标 假设我们有一个输入向量uint32 t std vector
  • “此应用程序已请求运行时以异常方式终止它”的原因是什么?

    Visual C 运行时抛出一个常见错误 此应用程序已请求运行时以异常方式终止它 请联系应用程序的支持团队以获取更多信息 该错误消息实际上是什么意思mean 让我用一个比喻来准确地解释我的问题 如果我看到一条消息 异常 访问冲突 0xc00
  • 这个按位运算如何检查 2 的幂?

    我正在看一些应该很简单的代码 但我的数学在这里严重失败 下面是一个使用以下条件检查数字是否为 2 的幂的条件 if num 1 num num 1 make num pow of 2 我的问题是 如何在 num 和 num 1 之间使用按位
  • 在网络上编写数学方程的最佳方法是什么?

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 我正在开发一个与数学相关的网页 并正在寻找一种将数学方程轻松写入网页的解决方案 目前我可以使用
  • 使用多级解决方案计算二维网格中的最近邻

    我有一个问题 在 x y 大小的网格中 我提供了一个点 并且我需要找到最近的邻居 在实践中 我试图在 pygame 中找到距离光标最近的点 该点跨越颜色距离阈值 计算如下 sqrt rgb1 0 rgb2 0 2 rgb1 1 rgb2 1
  • 在常数空间中创建 1..N 的随机排列

    我正在寻找枚举固定空间中数字 1 N 的随机排列 这意味着我无法将所有数字存储在列表中 原因是 N 可能非常大 超过可用内存 我仍然希望能够一次遍历这样一个数字的排列 只访问每个数字一次 我知道对于某些 N 可以这样做 许多随机数生成器随机
  • iPhone 3GS 上的 ARM 与 Thumb 性能比较,非浮点代码

    我想知道是否有人有关于 iPhone 3GS 上 ARM 与 Thumb 代码性能的硬性数据 特别是对于非浮点 VFP 或 NEON 代码 我知道 Thumb 模式下的浮点性能问题 更大的 ARM 指令的额外代码大小是否会在某个时刻成为性能
  • 直接选择排序与交换选择排序

    有什么区别直接选择排序 vs 交换选择排序 今天我陷入了一场争论 我的教授在他的讲义中使用了这两个术语 维基百科和任何教科书或网站都会为您提供的选择排序就是他所说的 交换选择排序 我以前从未听说过 交换选择排序 这个术语 仅 选择排序 并且
  • 两个程序对象运行时比较的方法

    我正在进行一种特定类型的代码测试 该测试相当麻烦并且可以自动化 但我不确定最佳实践 在描述问题之前 我想澄清一下 我正在寻找合适的术语和概念 以便我可以阅读有关如何实现它的更多信息 当然 欢迎就最佳实践提出建议 但我的目标很具体 这种方法叫
  • GCC的sqrt()编译后如何工作?使用哪种root方法?牛顿-拉夫森?

    只是对标准感到好奇sqrt 来自 GCC 上的 math h 我自己编码的sqrt 使用牛顿拉夫森来做到这一点 是的 我知道 fsqrt 但CPU是如何做到这一点的呢 我无法调试硬件 现代 CPU 中的典型 div sqrt 硬件使用 2
  • 数学组合的完美最小哈希

    首先定义两个整数N and K where N gt K 两者都在编译时已知 例如 N 8 and K 3 接下来 定义一组整数 0 N or 1 N 如果这使答案更简单 并调用它S 例如 0 1 2 3 4 5 6 7 的子集数量S wi
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • .pdbs 会减慢发布应用程序的速度吗?

    如果 dll 中包含 pdb 程序调试 文件 则行号将出现在引发的任何异常的堆栈跟踪中 这会影响应用程序的性能吗 这个问题与发布与调试 即优化 无关 这是关于拥有 pdb 文件的性能影响 每次抛出异常时都会读取 pdb 文件吗 加载程序集时
  • 绘制多边形

    我正在使用 Google Maps API V3 根据路径绘制多边形 该路径是随机未排序坐标点 LatLng 的数组 这会产生以下形状 Polylines intersect Problem 由于多边形的形状取决于路径中点的顺序 因此如何对
  • IIS7 上的 ASP.NET 应用程序 - iisreset 后启动速度非常慢

    我有一个在 Windows 2008 上的 IIS7 下运行的 ASP NET 3 5 网站 当我重新启动 IIS iisreset 然后点击一个页面时 初始启动非常慢 我在 Process Explorer 中看到以下活动 w3wp ex
  • Haskell:IORef 的性能

    我一直在尝试在 Haskell 中编码一个需要使用大量可变引用的算法 但与纯粹的惰性代码相比 它 也许并不奇怪 非常慢 考虑一个非常简单的例子 module Main where import Data IORef import Contr
  • 使用 APDU 命令的有效 NFC 读取比特率是多少?

    我目前正在使用 Android IsoDep trancieve 函数发送和接收累计 1628 字节的数据 该函数分布在 35 个 APDU 命令 选择应用程序 身份验证 读取 中 字节计数包括返回的 MAC 校验和以及由 transcie
  • 在 O(n) 时间内排序?

    我被这个问题困扰了 2周 知道如何处理它吗 令 L 为 n 个不同整数的列表 假设 L 的 x 的元素在 1 750 范围内 设计线性排序算法对 L 的元素进行排序 我已经尝试过插入排序 但我不确定我的方法是否正确 Construct an

随机推荐