[英]Most efficient way to sort a 2d array with sorted rows into 1d sorted array
給定一個二維數組(矩陣),其中包含n行和k列,並且對行進行了排序,未指定列,那么對它進行排序的最有效算法是什么?
例如:
Input (n = 3 ; k = 4):
1 5 8 10
3 4 5 6
2 3 3 9
Output:
1 2 3 3 3 4 5 5 6 8 9 10
這純粹是算法問題,因此某些語言沒有特定的.sort()方法對我有幫助,因為我實際上對運行時復雜性感興趣。
我想到的是一種算法,如下所示:
- Build a Binary Search tree with n nodes. Each node contains:
ID - of the row it refers to;
Value - The number at the "head" of the row.
- Sort the tree where the sorting key are the values.
- Find the lowest valued node.
- Do while the tree has a root:
- Take the lowest value and append it to the new array.
- Update the node's value to the next one in the same row.
- If the updated value is null, delete that node.
- else re-sort the tree.
- If the node moved, the first node it swapped with will be the next lowest
- else, if it didn't move, it's the new lowest.
如果我沒有記錯的話,運行時復雜度為O(n*k * log n)
,因為我對樹進行了n*k
次排序,這花費了O(log n)
時間,而找到下一個最低位的過程為O(1)
。
如果我的復雜度計算錯誤,請告訴我。
有什么方法比這更有效嗎?
您基本上有n
排序的列表,每個列表的大小均為k
。 您需要通用化merge-sort ,這是k路合並。
想法是保留min-heap ,其中包含每個列表中的最小元素。
現在,迭代彈出堆的最小值。 將此數字設為x
,並說它是從第i
行獲取的。 現在,將x
附加到結果列表,然后將第i
行中的下一個元素添加到最小堆中(如果存在)
重復直到所有元素用盡。
復雜度為O(n*k*logn)
,考慮到您正在排序n*k
元素,並且需要遍歷所有元素,這非常有效。 使用二進制堆的常量非常好。
請注意,這通常被稱為外部排序 (或者確切地說是外部排序第二部分的近似變體)。
這與您建議的算法非常相似,但是由於使用了堆而不是效率較低的樹,因此運行速度可能會更快(具有更好的常量)。
還要注意,如果使用“常規”二叉樹,則會得到O(n^2k)
復雜度,因為無法保證樹的高度。 您需要一個自平衡二進制搜索樹才能獲得O(nklogn)
運行時間。
這可以使用有序合並來完成,這將花費o(rows * cols)時間,即元素總數和o(rows)空間復雜度。
此問題的Java代碼如下:(考慮行= 3,列= 4)
for(int i=0;i<3;i++)
{
index[i] =0;
}
int count=0;
int a;
int b;
int c;
while(count<(ROWS*COLS))
{
int smallest;
if(index[0]>=COLS)
a= Integer.MAX_VALUE;
else
a= matrix[0][index[0]];
if(index[1]>=COLS)
b = Integer.MAX_VALUE;
else
b = matrix[1][index[1]];
if(index[2]>=COLS)
c = Integer.MAX_VALUE;
else
c = matrix[2][index[2]];
if(a<=b && a<=c){
// a is smallest
smallest = a;
index[0] = index[0] +1;
}else if(b<=c && b<=a){
//b is smallest
smallest = b;
index[1] = index[1] + 1;
}else{
//c is smallest
smallest = c;
index[2] = index[2] + 1;
}
System.out.print(smallest + ", ");
count++;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.