在一个数组中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序数对。给定一数组,统计数组中的逆序数对。
比较经典的题目,用来练习一下归并排序。写了两个算法,都是O(nlgn),不过算法2效率应该会稍微高一些, 因为少了lgn次的数组复制,不过写起来容易出错。
void MergeSort::test() {
int a[] = {2, 1, -6, 3, -2, 8, 3, 9, 7, 6};
//int a[] = {8, 1, 2, -2};
cout << "Before sort the array is: ";
print(a, sizeof(a)/sizeof(int));
sort(a, sizeof(a)/sizeof(int));
cout << "After sort the array is: ";
print(a, sizeof(a)/sizeof(int));
cout << endl;
}
void MergeSort::sort(int *data, int n) {
int *tmp = new int[n];
for (int i = 0; i < n; ++i) {
tmp[i] = data[i];
}
int count = mergeSort1(data, 0, n - 1, tmp);
// int count = mergeSort2(tmp, 0, n - 1, data);
cout << "The count of inverse pairs is: " << count << endl;
delete []tmp;
}
int MergeSort::mergeSort1(int *data, int left, int right, int *tmp) {
int count = 0;
if (left < right) {
int mid = left + (right - left) / 2;
count += mergeSort1(data, left, mid, tmp);
count += mergeSort1(data, mid + 1, right, tmp);
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (data[i] <= data[j]) {
tmp[k++] = data[i++];
}
else {
tmp[k++] = data[j++];
count += mid - i + 1;
}
}
while (i <= mid) {
tmp[k++] = data[i++];
}
while (j <= right) {
tmp[k++] = data[j++];
}
for (i = left; i <= right; ++i) {
data[i] = tmp[i];
}
}
return count;
}
int MergeSort::mergeSort2(int *data, int left, int right, int *tmp) {
int count = 0;
if (left < right) {
int mid = left + (right - left) / 2;
count += mergeSort2(tmp, left, mid, data);
count += mergeSort2(tmp, mid + 1, right, data);
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (data[i] <= data[j]) {
tmp[k++] = data[i++];
}
else {
tmp[k++] = data[j++];
count += mid - i + 1;
}
}
while (i <= mid) {
tmp[k++] = data[i++];
}
while (j <= right) {
tmp[k++] = data[j++];
}
}
return count;
}