给定一串数字,求这串数字的逆序数。
- 用两个for循环,O(N^2)的复杂度,最容易考虑到的
- 用归并排序的方式。
利用树状数组,这个方法等到写数状数组的时候再写。
归并排序求逆序数的方法
假如归并时,将a[n]分成a(1,,,mid)和a(mid+1,,, j) 两部分,排序后得到如下的串:
1 3 4 8 9 (前半部分)
2 5 6 7 10 (后半部分)
如果4>2(str1[i]>str2[j]),说明4后面那几个数都比2大,所以此时逆序数就有len1-i+1。
下面是代码:
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <cstring>
#include "stdio.h"
using namespace std;
int temp[100]; //存储已排序的数组
int ans; //代表逆序数的个数
int a[100] = { 1,8,6,3,4,2}; //存储原数组信息
void merge(int i, int mid, int j) {
int left = i;
int right = j;
int m = mid + 1;
int t = i; //递增temp数组的插入元素位置
while (left <= mid && m <= j) { //两部分数组都没到尽头
if (a[left] > a[m]) {
temp[t++] = a[m++];
ans += mid - left + 1; //逆序数计算
}
else
temp[t++] = a[left++];
}
while (left <= mid) { //如果其中一个数组先遍历完了,就添加上剩下的那个数组的剩余元素
temp[t++] = a[left++];
}
while (m <= j) {
temp[t++] = a[m++];
}
for (int k = i; k <= j; k++) { //把数组替换到a数组中
a[k] = temp[k];
}
}
void mergesort(int i, int j) {
if (i < j) {
int mid = (j + i) / 2;
mergesort(i, mid);
mergesort(mid + 1, j);
merge(i, mid, j);
}
}
int main() {
ans = 0;
mergesort(0, 5);
printf("%d\n", ans);
return 0;
}