本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。
输入格式
第一行包含整数 n,表示数列的长度。
第二行包含 n 个整数,表示整个数列。
输出格式
输出一个整数,表示逆序对的个数。
数据范围
1≤n≤100000 数列中的元素的取值范围 [1,10^9]。
输入样例:
6
2 3 4 5 6 1
输出样例:
5
思路
归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。 归并排序 归并排序
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11,;
逆序数为14;
在分治后的每一层合并中顺便求出逆序对数量
归并排序分治我们求的是从小到大的顺序
我们所求的逆序对恰好是逆序数量,与归并排序不谋而合。
ac代码
c++
#include<iostream>
using namespace std;
typedef long long l1;
const int N =1000001;
int n;
int arr[N], tmp[N];
l1 merge_sort(int l,int r) {
if(l>=r) return 0;
int mid = l+r>>1;
l1 res =merge_sort(l,mid)+merge_sort(mid+1,r);
int k = 0,i=l,j= mid+1;
while(i<=mid&&j<=r){
if(arr[i]<=arr[j]) tmp[k++] = arr[i++];
else {
tmp[k++] = arr[j++];
res+= mid-i+1;
}
}
while(i<=mid) tmp[k++] = arr[i++];
while(j<=r) tmp[k++] = arr[j++];
for(int i = l,j=0;i<=r;i++,j++) arr[i] = tmp[j];
return res;
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>arr[i];
cout<<merge_sort(0,n-1)<<endl;
return 0;
}
Java
import java.io.*;
public class Main{
public static final int N = 100010;
public static int[] temp = new int[N];
public static void main(String args[]) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
String [] str = reader.readLine().split(" ");
int[] arr = new int[n];
for(int i = 0;i < n;i++) arr[i] = Integer.parseInt(str[i]);
System.out.print(sort(arr,0,n - 1));
}
public static long sort(int [] arr,int l,int r){
if(l >= r) return 0;
int mid = l + r >> 1;
long res = sort(arr,l,mid) + sort(arr,mid + 1,r);
int idx = 0,i = l,j = mid + 1;
while(i <= mid && j <= r){
if(arr[i] <= arr[j]) temp[idx++] = arr[i++];
else{
res += mid - i + 1;
temp[idx++] = arr[j++];
}
}
while(i <= mid) temp[idx++] = arr[i++];
while(j <= r) temp[idx++] = arr[j++];
for(i = l,j = 0;i <= r;i++,j++) arr[i] = temp[j];
return res;
}
}