题目要求:对归并排序进行修改,要求合并过程的空间复杂度为O(1)
解题思路:
假设a[beg, mid]和b[mid+1,end]是两段有序的子段,分别记做A和B,现要对其进行合并
1) 首先对A进行搜索,找到比B[0]大的第一个位置,记录为i,即A[0~i-1] < B[0],而A[i] > B[0];
2) 对B进行搜索,找到大于A[i]的第一个位置,记录为j,则B[0~j-1]<B[i]
3) 将A[i,mid], B[0,j-1] 进行旋转,使得B[0,j-1]旋转到左边,得到B[0,j-1] A[i, mid]
4)A[i, mid] B[j, end]是原来问题的一个子问题,继续上述1)-3)的步骤
下面是具体实现的代码:
#include <iostream>
using namespace std;
void reverse(int *array, int beg, int end)
{
while(beg < end)
{
int tmp = array[beg];
array[beg] = array[end];
array[end] = tmp;
++beg;
--end;
}
}
void rotate(int *array, int beg, int end, int len)
{
len = len % (end - beg + 1);
reverse(array, beg, end - len);
reverse(array, end - len + 1, end);
reverse(array, beg, end);
}
void merge(int *array, int beg, int mid, int end)
{
int i = beg;
int j = mid + 1;
while(i <= end && j <=end && i < j)
{
while(i <= end && array[i] < array[j])
{
++i;
}
int k = j;
while(j <= end && array[j] < array[i])
{
++j;
}
if(j > k) // 注意这个条件
{
rotate(array, i, j-1, j-k);
}
i += (j -k + 1);
}
}
void mergeSort(int *array, int beg, int end)
{
if(beg == end)
return;
int mid = (beg + end) >> 1;
mergeSort(array, beg, mid);
mergeSort(array, mid + 1, end);
merge(array, beg, mid, end);
}
int main()
{
int array[] = {8, 7, 6, 5, 4, 3, 2, 1};
int beg = 0;
int end = sizeof(array) / sizeof(int) - 1;
mergeSort(array, beg, end);
for(int i=beg; i<=end; ++i)
{
cout << array[i] << " ";
}
cout << endl;
return 0;
}