题目描述
这个算法的空间复杂度为O(1),因为只需要长度为10的数组。时间复杂度为O(10n),每次遍历一个元素,要统计数组中位于这个元素后面比他小的元素的个数,因此是10n。在n>1024时,本算法优于二分算法解决此问题(二分算法解决此问题的时间复杂度为O(nlogn),并且二分算法的空间复杂度为O(n))。
int InversePairs(vector<int> data) {
//如果数组为空,返回逆序对数为0
if (data.empty()){
return 0;
}
//从后向前遍历数组中的元素,同时用一个数组(哈希表)保存每个数字出现的次数
//每访问数组中的一个元素,就统计逆序对的个数
int inverse = 0;
vector<int> numbers(10, 0);
for (vector<int>::iterator ite = data.end() - 1; ite >= data.begin(); ite--){
int index = *ite;
inverse += sum(numbers, index);
numbers[index]++;
}
return inverse;
}
int sum(vector<int> &numbers, int &index){
int s = 0;
for (int i = 0; i < index; i++){
s += numbers[i];
}
return s;
}
解法二:剑指offer上指出,采用二分方法求解数组中的逆序对。
将数组分成两个子数组,分别求出这两个子数组的逆序对,并同时对这两个子数组排序。然后求出整个子数组的逆序对,并对整个子数组排序。
此算法的时间复杂度为O(nlogn),空间复杂度为O(n)。
int InversePairs(vector<int> data) {
if (data.empty()){
return 0;
}
int inverse = 0;
vector<int> tmpdata(data.size(), 0);
InversePairs(data, tmpdata, 0, data.size() - 1, &inverse);
return inverse;
}
void InversePairs(vector<int> &data, vector<int> &tmp, int begin, int end, int *times){
if (begin == end){
return;
}
int mid = (begin + end) / 2;
InversePairs(data, tmp, begin, mid, times);
InversePairs(data, tmp, mid + 1, end, times);
int first, second, index;
first = mid;
second = end;
index = end;
while ((first >= begin) && (second >= mid + 1)){
if (data[first] > data[second]){
tmp[index] = data[first];
(*times) = (*times) + (second - mid);
first--;
index--;
}
else {
tmp[index] = data[second];
second--;
index--;
}
}
while (first >= begin){
tmp[index] = data[first];
first--;
index--;
}
while (second >= mid + 1){
tmp[index] = data[second];
index--;
second--;
}
for (int i = begin; i <= end; i++){
data[i] = tmp[i];
}
return;
}