分治算法之求逆序对数
来源:互联网 发布:渭南广电网络客服电话 编辑:程序博客网 时间:2024/06/06 10:42
问题:有一实数序列a1,a2…an,若i < j 且 ai > aj,则(ai,aj)构成了一个逆序对,请使用分治方法求整个序列中的逆序对的个数,并分析算法的时间复杂度。
答:这个问题最简单的方法就是遍历整个序列,判断实数与它后面的每个实数是否构成逆序对,这种算法的时间复杂度为Ο(n2)。
如果用分治方法求出逆序对数,这就类似与归并排序算法。先将数组从中间分成两个部分,然后分别递归左半部分和右半部分,再合并排好序的左右两个部分,从而统计逆序对数。比如合并两个排好序的数组{1,4,5,7}和{2,3},
1. 先比较后取出1,再比较发现2小于4,那么2肯定小于4后面的元素,从而构成了(4,2),(5,2),(7,2) 3个逆序对。
2. 取出2后,再比较4和3,3<4,所以3和4以及后面的元素都构成了逆序对,共3对。
利用这个方法将数组的左半边和右半边递归分解,在合并过程中统计逆序对的个数。
代码:#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int n=0;//全局变量,用于统计逆序对数
void merge(int a[],int first,int mid,int last)
{
int *temp = new int[last-first+1];//临时数组,用于临时存放比较后的数字
int i=first,j=mid+1,k=0;
while(i<=mid&&j<=last)//遍历比较左右两个部分
{
if(a[i]<=a[j])
temp[k++] = a[i++]; //左半部分元素小于右半部分的元素,将左边该元素存入临时数组
else
{
temp[k++] = a[j++];
n=n+(mid-i+1);//统计左半边能和右半边该元素构成的逆序对数
}
}
while(i<=mid)
temp[k++]=a[i++];
while(j<=last)
temp[k++]=a[j++];
for(i=0; i < k;i++)
a[first + i] = temp[i];//从临时数组取出放回原数组
}
void mergesort(int a[],int first,int last)
{
if(first < last)
{
int mid = (first+last)/2;
mergesort(a,first,mid);//递归排序左半部分
mergesort(a,mid+1,last);//递归排序右半部分
merge(a,first,mid,last);//将处理后的两个部分合并
}
}
int main(int argc, char** argv) {
int a[6] = {6,5,4,3,2,1},i;
cout<<"序列:";
for(i=0;i<6;i++)
cout<< a[i] <<" ";
cout << endl;
mergesort(a,0,5);
cout << endl<< "逆序对数:" << n << endl;
return 0;}
运行结果:
时间复杂度分析:
每次都要将序列的的n个元素合并,时间复杂度为O(n),由于每次都将数组分成两部分,所以一共分了log2n次,所以,该算法时间复杂度为O(n* log2n).
- 分治算法之求逆序对数
- 分治 求逆序对数
- 分治法求逆序对数
- 分治求逆序对算法
- 归并排序算法求逆序对数
- 【算法】求一个数组中的逆序对数
- 归并排序与分治法求逆序对数
- 求逆序对数
- 求逆序对数
- 求数组逆序对数
- 10.求逆序对数
- 求逆序对数
- poj 求逆序对数
- 1:求逆序对数
- 归并求逆序对数
- openjudge 求逆序对数
- 归并求逆序对数
- poj1804求逆序对数
- 关于C++中的构造函数、拷贝构造函数、析构函数的总结
- wpf得到窗口或控件的句柄
- windows10 opengl配置
- 远程备份和恢复Oracle数据库PL/SQL
- Tcpdump抓包命令详解
- 分治算法之求逆序对数
- Hyper - 基于虚拟化的Docker engine
- 泛型高级——通配符
- 优化后的makefile模板替换
- 【bzoj 1293】[SCOI2009] 生日礼物 指针维护队列
- 操作系统精髓与设计原理--并发性:死锁和饥饿
- mac 安装软件记录
- 数据结构实验之栈七:出栈序列判定
- cd123