原题: 给定两有序数组,长度都是n,在总共n^2个两两之和中,找到最小的k个值。
题目不新鲜,出现了也有很多年了,不过在目前的面试中还有使用。较好的方法显然是用最小堆,时间复杂度降到 O(klgk)不过网上大略搜了一下,没有找到完整实现,甚至连关键点都没提到,我这里就算是个补充吧。
用最小堆,元素是 A[i] + B[j]. 每次弹出堆顶,然后插入新元素,维护最小堆。这里的关键在于每次插入哪些元素。大多数人说的都是,对于弹出A[i] + B[j], 应该插入A[i+1] + B[j], 以及A[i] + B[j+1]。我们来看看事实是什么。
已有A,B 两数组,假设从0开始升序排列。
如果当前最小堆弹出了A[1]+B[0], 那么接下来显然应该插入A[1] + B[1], 同时还有A[2] + B[0]. A[3]以上的组合不必考虑,因为A[2] + B[0]才刚刚插入。
如果当前弹出了A[1] + B[1], 那么插入A[1] + B[2]. 还有其他要插的么? 其实已经没还有了。由于A[2] + B[0]已在堆中还未弹出,所以A[3] 以上的组合全都不用入堆。
简单列个表格如下, 弹出项除(0,0)外全都是假设:
selected(i, j) heap
(0,0)

这篇博客介绍了如何利用最小堆解决在两个有序数组中找到两两之和的最小k个值的问题。通过分析弹出堆顶元素后应插入的元素,得出只有在j=0时才需要插入(i+1, 0),并讨论了局部冗余和实现细节。博主提供了完整的C++代码实现,并指出此方法的时间复杂度为O(klgk)。"
127061365,5814479,使用CSS3实现无限循环动画特效,"['CSS', 'CSS3', '前端框架']
最低0.47元/天 解锁文章
2639

被折叠的 条评论
为什么被折叠?



