簡體   English   中英

將帶有排序行的2d數組排序為1d排序數組的最有效方法

[英]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.

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