用归并排序处理逆序对问题
2016-01-03 00:19
453 查看
首先了解一下什么是逆序对,
对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。
例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。
然后了解一下什么是归并排序:
接下来让我们看看求逆序对的代码:
两者的差别在于多了一个计数器count1。
如果左数组比右数组大,那么是逆序对,由于左右数组是有序的(从小到大),当左数组中M比右数组中N大,那么M左边的数也比右数组中的N大。所以count1=count1+mid-i+1.
伪原创。
对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。
例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。
然后了解一下什么是归并排序:
void Merge(int a[] , int low, int mid, int high,int b[]) { int i = low; // i是第一段序列的下标 int j = mid + 1; // j是第二段序列的下标 int k = 0; // k是临时存放合并序列的下标 // b是临时合并序列 // 扫描第一段和第二段序列,直到有一个扫描结束 while (i <= mid && j <= high) { // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描 if (a[i] <= a[j]) { b[k] = a[i]; i++; k++; } else { b[k] = a[j]; j++; k++; } } // 若第一段序列还没扫描完,将其全部复制到合并序列 while (i <= mid) { b[k] = a[i]; i++; k++; } // 若第二段序列还没扫描完,将其全部复制到合并序列 while (j <= high) { b[k] = a[j]; j++; k++; } // 将合并序列复制到原始序列中 for (k = 0, i = low; i <= high; i++, k++) { a[i] = b[k]; } } void MergeSort(int a[],int low,int high,int b[]) {//用分治法对R[low..high]进行二路归并排序 int mid; if(low<high){//区间长度大于1 mid=(low+high)/2; //分解 MergeSort(a,low,mid ,b); //递归地对R[low..mid]排序 MergeSort(a,mid+1,b); //递归地对R[mid+1..high]排序 Merge(a,low,mid,high); //组合,将两个有序区归并为一个有序区 } }
接下来让我们看看求逆序对的代码:
#include<bits/stdc++.h> using namespace std; long long count1=0;//为了防止溢出,count用long long 定义 void merge(int a[],int low,int mid,int high,int b[])//合并 { int i=low,j=mid+1,k=0; while(i<=mid&&j<=high) { if(a[i]<=a[j]){ b[k++]=a[i++]; } else{ b[k++]=a[j++]; count1+=mid-i+1; } } while(i<=mid) { b[k++]=a[i++]; } while(j<=high) { b[k++]=a[j++]; } for(int m=0;m<k;m++) { a[low+m]=b[m]; } } void mergsort(int a[],int first,int last,int b[])//排序 { int mid; if(first<last) { mid=(first+last)/2; mergsort(a,first,mid,b); mergsort(a,mid+1,last,b); merge(a,first,mid,last,b); } } int main() { int n; cin>>n; int a ,b ; for(int i=0;i<n;i++) { cin>>a[i]; } mergsort(a,0,n-1,b); cout<<count1<<endl; return 0; }
两者的差别在于多了一个计数器count1。
如果左数组比右数组大,那么是逆序对,由于左右数组是有序的(从小到大),当左数组中M比右数组中N大,那么M左边的数也比右数组中的N大。所以count1=count1+mid-i+1.
伪原创。
相关文章推荐
- 在window7下安装mysql
- class_create(),device_create自动创建设备文件结点
- RMI基础知识
- 比比Java和C#语言运行的快慢
- maven项目建立
- Logback与Log4J的区别
- grunt安装失败处理
- 1.ARC下是否有内存溢出等问题 2.@property参数 3.#import和@class的区别
- Android Tab实现之FragmentManager+Fragment
- 被误解的 MVC 和被神化的 MVVM
- 九度OJ 1361(反转) 1362(循环移位) 1363(判断) 1364(01背包) 1365(BFS)
- Shell编程进阶 2.2 shell数组
- Oracle事务隔离级别
- Shodan完全手册部分翻译(4)
- 2015年总结
- ?--Porg.springframework.beans.MethodInvocationException: Property 'username' threw exception; nested exception is java.lang.NullPointerException
- Android的context
- Hdu 2118
- IAR切BANK--程序中的使用
- 【云计算】Docker与容器快速入门