Python 在k个数组中查找第a到第b个最小元素的有效方法
我最近接受了一家社交媒体公司的采访,他们问了我以下问题。Python 在k个数组中查找第a到第b个最小元素的有效方法,python,mysql,algorithm,sorting,time-complexity,Python,Mysql,Algorithm,Sorting,Time Complexity,我最近接受了一家社交媒体公司的采访,他们问了我以下问题。 有k个长度为m的未排序数组。目标是在给定a
有k个长度为m的未排序数组。目标是在给定a 我提出了两种可能的解决方案:
第一:暴力:
对于每个循环,执行以下操作
更有效的方法是什么?特别是quickselect最糟糕的情况是O(n^2),它看起来太大了,对于空间中位数O(kb)处的b=m/2或时间中位数O(b*log(k))被认为太大了。对于MySQL数据库,我建议在解决方案1中使用B-tree,它在空间和时间上都有O(kb)的情况下提供快速的排名选择,并且数据库中有k个查询。在解决方案2中,据说MySQL数据库中的b查询太大,b树插入为O(log(m)),其中m可能非常大。一个简单的方法是创建一个大小为b的最大堆。然后运行以下代码:
for arr in arrays // process each of the k arrays in turn
for i = 0 to length(k)-1
if heap.count < b
heap.push(arr[i])
else if (arr[i] < heap.peek())
heap.pop()
heap.push(arr[i])
最坏的情况是,使用O(b)额外内存,第一个循环为O(km log b),第二个循环为O(b log b)
如果允许销毁源阵列,则可以编写一个自定义quickselect,将k个阵列作为单个阵列进行索引。这将是O(km),使用O(k)额外内存作为间接索引。缺点是索引代码会稍微慢一些。当然,项目会在数组之间移动。您可能需要O(b)个额外的内存作为返回值。渐进地,它比我最初的选择更有效。它是否能跑得更快完全是另一个问题
还有一种可能性。在每个k数组上运行buildheap方法。那是O(公里)。然后进行合并以选择前b项。合并需要:
- O(log m)从源阵列中删除每个项
- O(日志b)将每个项添加到合并堆
- O(日志b)从合并堆中删除每个项
这样就得到了O(km+b*(logm+logb+logb)),并且需要使用O(b)额外的内存。这是否会比最初的建议更快是值得怀疑的。这取决于b和m之间的关系。b的值越大,速度越快。而且代码编写起来要复杂得多。你得到这份工作了吗?
// all items have been processed, take the first *b - a* items from the max heap
for i = 0 to (b-a-1)
result[i] = heap.pop()