给定一个带有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)
。
如果我的复杂性计算错误,请告诉我。
有没有比这更有效的方法?
答案 0 :(得分:3)
您基本上拥有n
个排序列表,每个列表的大小为k
。您需要merge-sort的泛化,这是k-way合并。
我们的想法是保留min-heap,其中包含每个列表中最小的元素。
现在,迭代地弹出堆的最小值。请将此数字设为x
,并说它来自行i
。现在,将x
附加到结果列表,并将最小的行添加到行i
中的下一个元素(如果存在这样的元素)
重复直到所有元素都用尽。
复杂性为O(n*k*logn)
,考虑到您正在排序n*k
元素并且需要遍历所有元素,这非常有效。使用二进制堆的常量非常好。
请注意,这通常被称为external sort(或者与外部排序的第二部分完全相同)。
这与您建议的算法非常相似,但由于使用堆而不是效率较低的树,可能会运行得更快(具有更好的常量)。
另请注意,如果您使用常规的'二叉树,你得到O(n^2k)
的复杂性,因为不能保证树的高度。您需要self balancing binary search tree才能获得O(nklogn)
运行时间。
答案 1 :(得分:0)
这可以使用Sorted Merge来完成,它将占用o(rows * cols)时间,即元素总数和o(行)空间复杂度。
此问题的java代码如下:(考虑rows = 3和cols = 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++;
}