归并排序查找逆序对
2015-11-23 12:21
399 查看
Description
Let A(1), ..., A(n) be a sequence of n numbers. If i<j and A(i)>A(j), then the pair (i,j) is called an inversion pair.
The inversion number of a sequence is one common measure
of its sortedness. Given the sequence A, calculate its inversion number.
Input
There are multiple cases.
Each case contains an integer n (n<=100,000) followed by A(1) , ..., A(n).
Output
For each case, output the inversion number.
Sample Input
Copy sample input to clipboard
Sample Output
题目分析
根据逆序对的定义,如果暴力比较,复杂度是O(n^2)
采用归并排序的话,可以将复杂度降到O(n*log(n))
假设左右都已经排好序,当右边的某个数i小于了左边的某个数j,
则i一定小于左边部分所有大于j的数,即这些都是逆序对
这样在最终排序完成时,可以找到所有的逆序对
由于归并排序的复杂度为O(n*log(n))
所以总的复杂度为O(n*log(n))
#include <iostream>
int arr[100001];
long long count;
void sort(int start, int end) {
int mid = (start+end) / 2;
int len1 = mid-start+1;
int len2 = end-mid;
int arr1[len1];
for (int i = 0; i < len1; ++i)
arr1[i] = arr[start+i];
int arr2[len2];
for (int i = 0; i < len2; ++i)
arr2[i] = arr[mid+1+i];
int index1 = 0;
int index2 = 0;
for (int i = start; i <= end; ++i) {
if (index1 == len1) {
arr[i] = arr2[index2++];
} else if (index2 == len2) {
arr[i] = arr1[index1++];
} else {
if (arr1[index1] <= arr2[index2]) {
arr[i] = arr1[index1++];
} else {
arr[i] = arr2[index2++];
////////////////////////////////////
count += (len1 - index1);
////////////////////////////////////
}
}
}
}
void merge(int start, int end) {
if (start < end) {
int mid = (start+end)/2;
merge(start, mid);
merge(mid+1, end);
sort(start, end);
}
}
int main()
{
int num;
while(std::cin >> num) {
for (int i = 0; i < num; ++i)
std::cin >> arr[i];
count = 0;
merge(0, num-1);
std::cout << count << std::endl;
}
}
Let A(1), ..., A(n) be a sequence of n numbers. If i<j and A(i)>A(j), then the pair (i,j) is called an inversion pair.
The inversion number of a sequence is one common measure
of its sortedness. Given the sequence A, calculate its inversion number.
Input
There are multiple cases.
Each case contains an integer n (n<=100,000) followed by A(1) , ..., A(n).
Output
For each case, output the inversion number.
Sample Input
Copy sample input to clipboard
5 3 1 4 5 2
Sample Output
4
题目分析
根据逆序对的定义,如果暴力比较,复杂度是O(n^2)
采用归并排序的话,可以将复杂度降到O(n*log(n))
假设左右都已经排好序,当右边的某个数i小于了左边的某个数j,
则i一定小于左边部分所有大于j的数,即这些都是逆序对
这样在最终排序完成时,可以找到所有的逆序对
由于归并排序的复杂度为O(n*log(n))
所以总的复杂度为O(n*log(n))
#include <iostream>
int arr[100001];
long long count;
void sort(int start, int end) {
int mid = (start+end) / 2;
int len1 = mid-start+1;
int len2 = end-mid;
int arr1[len1];
for (int i = 0; i < len1; ++i)
arr1[i] = arr[start+i];
int arr2[len2];
for (int i = 0; i < len2; ++i)
arr2[i] = arr[mid+1+i];
int index1 = 0;
int index2 = 0;
for (int i = start; i <= end; ++i) {
if (index1 == len1) {
arr[i] = arr2[index2++];
} else if (index2 == len2) {
arr[i] = arr1[index1++];
} else {
if (arr1[index1] <= arr2[index2]) {
arr[i] = arr1[index1++];
} else {
arr[i] = arr2[index2++];
////////////////////////////////////
count += (len1 - index1);
////////////////////////////////////
}
}
}
}
void merge(int start, int end) {
if (start < end) {
int mid = (start+end)/2;
merge(start, mid);
merge(mid+1, end);
sort(start, end);
}
}
int main()
{
int num;
while(std::cin >> num) {
for (int i = 0; i < num; ++i)
std::cin >> arr[i];
count = 0;
merge(0, num-1);
std::cout << count << std::endl;
}
}
相关文章推荐
- Java Font类
- 并行计算-学习笔记2
- 传智播客javase总结 5
- 详解 Android Activity 生命周期
- Angular 学习笔记——shop
- android shape的使用
- SQL2005安装及连接
- UltraEdit怎么批量删除指定字符所在的行
- 高雅的数学表示
- javaScript传递参数,参数变化问题
- tomcat修改内存
- PHP - 使用pear的HTTP_Upload包进行上传
- 内部类
- C#从SQL server数据库中读取l图片和存入图片
- 【Android】Gson-以类模板的方式解析复杂JSON
- java_SSH继续充电_struts2_第一天
- 误删除了mssql的表。 使用命令:drop table xxxx
- 技能CD 效果 shader
- GOF设计模式
- path和classpath的区别