`

逆序数/逆序数对

J# 
阅读更多
逆序数是个常遇到的问题,主要有两种解法:
O(n^2)的方法:
int reverse(int a[],int n){
	int count = 0;//逆序数
	for(int i = 0; i < n; i++){
		for(int j = i + 1; j < n; j++){
			if(a[i] > a[j])
				count++;
		}
	}
	return count;
}

O(n*logn)的方法,归并:
const int N = 500000;
int a[N];
int swap_space[N];//归并排序的交换空间
long long total;//逆序数
int total = 0;
void merge(int a[], int begin, int mid,int end){
	int i = begin;
	int j = mid + 1;
	int k = begin;

	while(i <= mid && j <= end){
		if(a[i] < a[j]){
			swap_space[k++] = a[i++];
		}else{
			swap_space[k++] = a[j++];
			total += (mid - i + 1);//total is the reverse count
		}
	}

	while(i <= mid)
		swap_space[k++] = a[i++];
	while(j <= end)
		swap_space[k++] = a[j++];

	for(i = begin; i <= end; i++){
		a[i] = swap_space[i];
	}
}

void mergeSort(int a[], int begin, int end){
	if(begin != end){
		int mid = (begin + end) / 2;
		mergeSort(a,begin, mid);
		mergeSort(a,mid+1, end);
		merge(a,begin,mid,end);
	}
}

学以致用:
poj2299:http://acm.pku.edu.cn/JudgeOnline/problem?id=2299
#include<iostream>
using namespace std;

const int N = 500000;
int a[N];
int swap_space[N];//归并排序的交换空间
long long total;//逆序数

void merge(int a[], int begin, int mid,int end){
	int i = begin;
	int j = mid + 1;
	int k = begin;

	while(i <= mid && j <= end){
		if(a[i] < a[j]){
			swap_space[k++] = a[i++];
		}else{
			swap_space[k++] = a[j++];
			total += (mid - i + 1);
		}
	}

	while(i <= mid)
		swap_space[k++] = a[i++];
	while(j <= end)
		swap_space[k++] = a[j++];

	for(i = begin; i <= end; i++){
		a[i] = swap_space[i];
	}
}

void mergeSort(int a[], int begin, int end){
	if(begin != end){
		int mid = (begin + end) / 2;
		mergeSort(a,begin, mid);
		mergeSort(a,mid+1, end);
		merge(a,begin,mid,end);
	}
}


int main(){
	int n;
	int i;

	while(cin >> n, n){
		total = 0;
		for(i = 0; i < n; i++){
			cin >> a[i];
		}
		mergeSort(a, 0 , n-1);
		cout << total << endl;
	}
}

第一种方法会超时。
有关于逆序数对再续。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics