2011-02-25 42 views
6

我有m個數組,每個數組的長度爲n。每個數組都進行排序。我想創建一個長度爲m * n的單個數組,包含前面數組的所有值(包括重複值),並進行排序。我必須合併這些陣列..合併排序後的數組,什麼是最佳時間複雜度?

我認爲最佳的時間複雜度M * N *日誌(M)

這裏的算法的草圖..

我創建支持數組h的長度爲m,包含每個數組的第一個元素的所有值。

然後我排序這個數組(m log m),並將最小值移到輸出數組。

然後,我將它移動的值替換爲下一個移動的值。其實我沒有取代它,但我把它插入右邊(排序)的位置。我認爲這需要記錄。

我再重複這個對所有m * n個值...因此M * N * log M的

我的問題..你能想到一個更有效的算法嗎?如果mnlogm實際上是最優的,你至少能想到一個更簡單,更優雅的算法嗎?

+3

如何插入排序數組中的元素取對數時間? – codaddict 2011-02-25 10:33:05

回答

11

複雜性是正確的!但是,算法思路中存在一個小缺陷:您無法在log m中的排序數組中插入項目。你可以在二進制搜索中找到它的位置,但你可能需要移動元素才能將它放置在那裏。要解決這個問題,你可以使用堆數據結構來代替!

多路合併(這是您算法的通用名稱)通常通過另一個'合併'數據結構來實現:比賽樹。你可以在Knuth的「計算機程序設計藝術」(排序章節,iirc)中找到描述。在這個具體情況下,與堆相比,它在理論上和實踐中具有較低的常數因子。

如果你想看實現,我敢肯定GNU C++標準庫並行擴展中的並行多路合併是以這種方式實現的。

編輯:我引用了錯誤的書,現在已經修復了。

+0

他們是否具有相同的時間複雜性?「多路合併與最小堆」和「多路合併與錦標賽樹」? (這裏,O(m n logm))如果不是,哪一個更高效?謝謝 – Hengameh 2015-06-03 10:20:04

+1

是的,它們具有相同的漸近時間複雜度,如果這就是你要求的! – ltjax 2015-06-07 14:09:35

0

你可以做的最好的是O(m * n + d)。類似於計數排序:http://en.wikipedia.org/wiki/Counting_sort如果您知道可能的值範圍(d,比如說),則可以初始化一個長度爲d的數組,然後掃描每個m數組,每個數組中添加1到每個「bin」到那個垃圾箱。然後,在d中爲每個值添加長度爲m * n的新數組,然後添加bin的許多計數。

+0

正如你所寫的,這隻有在你知道'd'並且你的值空間到整數有一個_easy_映射時纔有效。另外,內存複雜度在'd'中是線性的,如果您的值範圍很大,這可能很糟糕。所以這不一定更好。 – ltjax 2011-02-25 10:50:46

+0

是的,取決於他的數據集我想 – 2011-02-25 10:53:15

+0

我在ConcurrentLinkedHashMap中應用等待LRU操作之前這樣做,以便它們按嚴格順序執行。我連鎖衝突,例如封閉尋址。我認爲這種方法被稱爲有限高度優先隊列。 – 2011-02-26 07:49:27

相關問題