我获得了k个排序数组,需要将它们合并为一个排序数组。我们假设n是所有输入数组中元素的总数,并且k = 3。
public class Merge {
// Create a mergeklists() to merge 3 sorted arrays into one sorted array
// Input: 3 sorted arrays a1[], a2[], a3[]
// Output: one sorted array a[] that contains all the elements from input arrays
public static void merge3lists(int[] a1, int[] a2, int[] a3, int[] a)
{
int i=0;
int j=0;
int h=0;
int n = a1.length + a2.length + a3.length;
for(int k; a.length < n-1; k++){
if(a1[i] < a2[j]){
k = a1[i];
i++;
}
else if(a2[j] < a3[h]){
k = a2[j];
j++;
}
else{
k = a3[h];
h++;
}
}
}
public static void main(String[] args) {
int[] l1 = {1,5,9,10,20};
int[] l2 = {2,4,5,6,7,9,15};
int[] l3 = {3,8,13,15,22};
int[] newl = new int[l1.length+l2.length+l3.length];
merge3lists(l1,l2,l3,newl);
for(int i = 0; i< newl.length; i++)
{
System.out.print(newl[i]+ " ");
}
}
}
我知道我正在使用的整数(I,j和h)正在弄乱这个问题,但我不认为我可以在比较所有数组时使用i。我需要使用声明的数组a,但在这种情况下我不确定如何引用它。
答案 0 :(得分:4)
要使方法合并任意数量的数组(k
),您需要使用varargs方法。
让方法为你创建结果数组也会更好。
然后循环,直到填充结果数组。对于每次迭代,您可以找到每个源数组中下一个值的最小值,并将其添加到结果数组中,然后在您从中选择值的源数组中前进。
像这样:
public static int[] mergeArrays(int[]... arrays) {
// Create result array
int n = 0;
for (int[] a : arrays)
n += a.length;
int[] result = new int[n];
// Start at index 0 in each source array
int[] idx = new int[arrays.length];
// Merge source arrays into result array
for (int i = 0; i < n; i++) {
// Find smallest value
int minJ = -1, minVal = 0;
for (int j = 0; j < arrays.length; j++) {
if (idx[j] < arrays[j].length) {
int val = arrays[j][idx[j]];
if (minJ == -1 || val < minVal) {
minJ = j;
minVal = val;
}
}
}
// Add to result array and step forward in appropriate source array
result[i] = minVal;
idx[minJ]++;
}
return result;
}
测试
int[] merged = mergeArrays(new int[] { 23, 39, 63, 68 },
new int[] { 11, 21, 76 },
new int[] { 5, 10, 37, 80 },
new int[] { 30, 49, 50, 94 },
new int[] { 13, 25, 48 });
System.out.println(Arrays.toString(merged));
输出
[5, 10, 11, 13, 21, 23, 25, 30, 37, 39, 48, 49, 50, 63, 68, 76, 80, 94]
答案 1 :(得分:3)
看起来像是一个准备练习,以激励引入数组:)
将与列表类似的索引编号,以避免混淆。
标识当前索引处具有最小元素的列表。避免超出数组末尾读取,因为它会导致异常。
拿这个元素继续。
int i1=0;
int i2=0;
int i3=0;
int n = a1.length + a2.length + a3.length;
for( int k = 0; k < n; k++) {
int advance = 0;
int value = Integer.MAX_VALUE;
if (i1 < a1.length && a1[i1] <= value) {
advance = 1;
value = a1[i1];
}
if (i2 < a2.length && a2[i2] <= value) {
advance = 2;
value = a2[i2];
}
if (i3 < a3.length && a3[i3] <= value) {
advance = 3;
value = a3[i3];
}
a[k] = value;
switch(advance) {
case 1: i1++; break;
case 2: i2++; break;
case 3: i3++; break;
}
}
答案 2 :(得分:0)
更有效的算法是使用最小堆。
该算法大致描述如下:
首先,构造一个最小大小为k的最小堆(在这种情况下,三个列表的大小为3),并在每个列表中使用最少的元素。然后,您将删除堆中的最小元素(注意它来自哪个列表),将其添加到新构造的列表中,然后从最初绘制该列表的那个列表中插入下一个元素。
时间复杂度将从O(n * k)降至O(n * log(k))。其中n是最终排序列表中的元素总数。