题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
思路:判断两个数是否逆序就是判断前一个数是否大于后一个数,所以我们可以采用分治法,将一个数组序列折半分解为两个子序列,然后子序列继续对半分解,直至将子序列分解为两个数字。然后判断这两个数字是否逆序,如果逆序则逆序对数+1,然后将其合并为有序序列;将两个有序的子序列归并为一个新的有序序列,归并过程中统计逆序对数————因为两个序列都是有序序列,所以如果前一个序列的对头元素大于后一个序列的队头元素,则前一个序列中的所有元素相对于后一个序列的队头元素逆序,逆序对数就是前一个序列的长度,这样我们就可以统计出这两个序列中的逆序对数。一个序列的逆序对数是前半段序列的逆序对数+后半段序列逆序对数+归并这两个序列时新统计出来的逆序对数之和。
#include <stddef.h>
//统计逆序对数
int reverseOrderPair(int* array, int length) {
if (NULL == array || 0 >= length) {
return 0;
}
//辅助数组并利用array数组初始化
int* copy = new int[length];
for (int i = 0; i < length; ++i) {
copy[i] = array[i];
}
int count = allReverseOrderPair(array, copy, 0, length - 1);
delete[] copy;
return count;
}
//统计整个序列的逆序对数
int allReverseOrderPair(int* array, int* copy, int start, int end) {
if (NULL == array || NULL == copy || 0 > start || start > end) {
return 0;
}
if (start < end) {
int middle = (start + end) / 2;
int left = allReverseOrderPair(array, copy, start, middle);
int right = allReverseOrderPair(array, copy, middle + 1, end);
int current = subReverseOrderPair(copy, array, start, middle, end);
//逆序对数有三部分组成
return left + right + current;
}
return 0;
}
//统计相邻的两个序列中的逆序对数
int subReverseOrderPair(int* array, int* copy, int start, int middle, int end) {
if (NULL == array || NULL == copy || 0 > start || start > end) {
return 0;
}
int i = start, j = middle + 1;
int k = start, count = 0;
//统计相邻两个序列中的逆序对数并归并这两个序列
while (i <= middle && j <= end) {
if (array[i] < array[j]) {
copy[k++] = array[i++];
} else {
copy[k++] = array[j++];
//计算array[i]相当于另一个序列的逆序对数
count = count + middle - i + 1;
}
}
while (i <= middle) {
copy[k++] = array[i++];
}
while (j <= end) {
copy[k++] = array[j++];
}
return count;
测试代码
/*
*
* Created on: 2014-4-24 09:37:29
* Author: danDingCongRong
*/
#include<iostream>
using namespace std;
//输入各个数组元素
void inputArray(int* array, int length) {
cout << "输入这个数组中的各个数字:" << endl;
for (int i = 0; i < length; ++i) {
cin >> array[i];
}
}
int main() {
int length = 0;
cout << "请输入数组的长度:" << endl;
while (cin >> length) {
int* x = new int[length];
inputArray(x, length);
cout << "逆序对数:" << reverseOrderPair(x, length) << endl;
delete[] x;
cout << "请输入数组的长度:" << endl;
}
return 0;
}
注:参考自剑指offer