排序u,然后合并S和u。
合并只涉及同时遍历两个已排序的数组,并选择较小的元素并在每一步递增该迭代器。
运行时间为O(|u| log |u| + |S|)。
这与merge sort 所做的非常相似,因此它会导致可以从那里派生排序数组。
一些用于合并的 Java 代码,源自 Wikipedia:(C 代码看起来并没有什么不同)
static void merge(int S[], int u[], int newS[])
{
int iS = 0, iu = 0;
for (int j = 0; j < S.length + u.length; j++)
if (iS < S.length && (iu >= u.length || S[iS] <= u[iu]))
newS[j] = S[iS++]; // Increment iS after using it as an index
else
newS[j] = u[iu++]; // Increment iu after using it as an index
}
这也可以从后面就地完成(在 S 中,假设它有足够的额外空间)。
以下是执行此操作的一些有效 Java 代码:
static void mergeInPlace(int S[], int SLength, int u[])
{
int iS = SLength-1, iu = u.length-1;
for (int j = SLength + u.length - 1; j >= 0; j--)
if (iS >= 0 && (iu < 0 || S[iS] >= u[iu]))
S[j] = S[iS--];
else
S[j] = u[iu--];
}
public static void main(String[] args)
{
int[] S = {1,5,9,13,22, 0,0,0,0}; // 4 additional spots reserved here
int[] u = {0,10,11,15};
mergeInPlace(S, 5, u);
// prints [0, 1, 5, 9, 10, 11, 13, 15, 22]
System.out.println(Arrays.toString(S));
}
为了减少比较次数,我们还可以使用二分查找(虽然时间复杂度保持不变 - 这在比较昂贵时很有用)。
// returns the first element in S before SLength greater than value,
// or returns SLength if no such element exists
static int binarySearch(int S[], int SLength, int value) { ... }
static void mergeInPlaceBinarySearch(int S[], int SLength, int u[])
{
int iS = SLength-1;
int iNew = SLength + u.length - 1;
for (int iu = u.length-1; iu >= 0; iu--)
{
if (iS >= 0)
{
int index = binarySearch(S, iS+1, u[iu]);
for ( ; iS >= index; iS--)
S[iNew--] = S[iS];
}
S[iNew--] = u[iu];
}
// assert (iS != iNew)
for ( ; iS >= 0; iS--)
S[iNew--] = S[iS];
}
如果S 不必是数组
以上假设S 必须是一个数组。如果没有,binary search tree 之类的可能会更好,具体取决于 u 和 S 的大小。
运行时间为O(|u| log |S|) - 只需替换一些值即可查看哪个更好。