Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note:
You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.
思路:
我们当然可以立刻想到,申请一块新的长度为m+n的数组,进行归并排序,然后把数组拷贝(或者交换)回去。这个如果可以使用std::vector和swap的话,似乎也是一个有效的方法。但是题目中给定的参数是C数组,所以看来需要进行拷贝。这样归并的时间复杂度是O(m+n),同时拷贝的时间复杂度也是O(m+n)。
当然,如果这是面试题的话,那么问题可能没这么简单。可以做一个假设:面试官要求只能使用O(1)的空间。这样就不得不考虑利用数组A中的额外空间作为临时储存数据的地方。
一开始的考虑是,将merge时较大的数据保存在A数组额外的空间里,但是这样的话,需要考虑的情况很多,例如m和n之间的关系等等。
另外的考虑是,merge的数据保存在A额外的空间中,当额外空间用完之后,开始从A的起点开始继续,这时只要A的数据有被归并的话,起点数据是可以作废的。归并到最后,得到一个向左旋转n的数组。有关rotate和reverse之间的关系参见编程珠矶相关章节。
题解:
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
// Iterator used through merging
int merge_A = 0;
int merge_B = 0;
// merge is done at the end of m-th element, A[]
int merge_iter = m;
while(merge_A < m || merge_B < n)
{
// check if we reached the end of merge region, if so,
// start from beginning
if (merge_iter == m + n)
merge_iter = 0;
if (merge_A == m) // merge A is done
A[merge_iter++] = B[merge_B++];
else if (merge_B == n) // merge B is done
A[merge_iter++] = A[merge_A++];
else
A[merge_iter++] = (A[merge_A] < B[merge_B] ? A[merge_A++] : B[merge_B++]);
}
// merge is complete, now the array looks like
// 4567 | 123
// so we need to reverse it -- ref. Programming Pearls
reverse(A, A+m);
reverse(A+m, A+m+n);
reverse(A, A+m+n);
}
};