簡體   English   中英

在k個數組中查找第a至第b最小元素的有效方法

[英]Efficient way to find the a-th to b-th smallest elements across k arrays

最近,我接受了一家社交媒體公司的采訪,被問到以下問題。

k個長度為m的未排序數組。 目標是在給定a < b < m的情況下,以有效且記憶保守的方式在k個數組中找到 a至第b的最小元素。 在后續問題中,將“未排序的數組”更改為MySQL數據庫中不同表的列,可以使用什么可能的有效數據結構以及相應的檢索算法。

我提出了兩種可能的解決方案:

第一:蠻力:

  1. 首先使用quickselect找到每個數組的第b個最小元素。
  2. 然后找到小於每個數組第b個元素的元素,並將其存儲到大小為k * b的 B樹C中
  3. 然后在C中找到第a到第 b的最小元素。

要使用quickselect查找第b個最小元素的第一步,平均時間總計為O(km)O(km * log(m)) 步驟2時間復雜度為O(km) 最后一步是在C中找到位於 a個元素與第 b個元素之間元素,取O((ba)log(kb)) 因此,總計需要O(km)O(km * log(m)) + O((ba)log(kb))的時間,以及O(kb)的空間。

第二:遞歸地彈出最小的元素

對於每個循環,執行

  1. 找到所有k個數組的最小元素,存儲在B樹C中
  2. C中找到最小的元素,然后從C中彈出該元素,然后從數組中彈出該元素。
  3. 重復直到彈出a-1數字,然后轉到4
  4. 重復1到2時,存儲從ab的值

因此,計算復雜度為O(k * log(k)) + O(b * log(k)) ,空間復雜度為O(max(k,ba)) 這似乎是最小的空間復雜度。

有哪些更有效的方法? 特別是快速選擇的最壞情況是O(n ^ 2) ,它似乎太大了,並且對於b = m / 2恰好在空間的中值O(kb)或時間上的O(b * log(k))處考慮太大。 對於MySQL數據庫,我建議使用B樹,該B樹在解決方案1中提供了快速的排名選擇,而空間和時間仍然是O(kb) ,其中k個查詢進入數據庫。 在解決方案2中,據說b對MySQL DB的查詢太大,而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])

這里的想法是用前b個項目填充最大堆。 然后,對於其他所有項目,如果它小於堆中的最大項目,則使用新項目刪除堆中的最大項目。

處理完所有km個項目后,堆上最小的b個項目,由於是最大堆,因此您彈出的前ba個項目將是所有k個數組中的 a到 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()

最糟糕的情況是,使用第一個循環的O(km log b),使用第二個循環的O(b log b),使用O(b)附加內存。

如果可以銷毀源數組,則可以編寫一個自定義的quickselect來將k個數組索引為單個數組。 這將是O(km),將O(k)的額外內存用於間接索引。 缺點是索引代碼會稍微慢一些。 而且,當然,這些項將在數組之間移動。 而且您可能想要O(b)額外的內存作為返回值。 漸近地,它比我最初的選擇更有效。 它是否會運行得更快,完全是另一個問題。

另一種可能性。 k個數組中的每一個上運行build-heap方法。 那將是O(km)。 然后進行合並以選擇前b個項目。 合並將需要:

  • O(log m)從源數組中刪除每個項目
  • O(log b)將每個項目添加到合並堆
  • O(log b)從合並堆中刪除每個項目

第二步將是O(b *(log m + log b + log b))。

這樣總共得到O(km + b *(log m + log b + log b)),並且您將使用O(b)額外的內存。 這是否會比最初的建議更快。 這取決於bm之間的關系。 b的值越大,越快越不可能。 而且代碼編寫起來要復雜得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM