求解逆序对数的几种方法
来源:互联网 发布:淘宝拍卖业务管理规范 编辑:程序博客网 时间:2024/05/17 05:02
求解逆序对数的几种方法:
设A为一个包含n个数字的有序集合
如果存在两个正整数i,j,使得
1. 两重循环来求解,时间复杂度为O(n2) ,大致代码如下:
int GetReverse(int* a, int n) { int sum = 0; for (int i = 0; i < n-1; ++i) { for (int j = i+1; j < n; ++j) { if (a[i] > a[j]) ++sum; } } return sum;}
2. 树状数组求解,时间复杂度O(nlogn)
大致思想:
假设我们有个标记数组flag,长度为n;
先在n个数中找到最大的元素e1,其下表为p1,将flag[p1]置为1,统计p1之前的1的个数,即为与e1构成的逆序对数;
找到第二大元素e2,其下标为p2,将flag[p2]置为1,统计p2之前的1的个数,即为与e2构成的逆序对数;
以此类推,全部找完之后,统计的总个数即为序列中逆序对的总数。
拿开头的例子来说:
3 1 4 5 2,初始状态flag数组均为0(约定下标从1开始);
取最大数5,flag数组变为 0 0 0 1 0,统计下标4之前的1的个数为0,总逆序对数为0;
取第二大数4,flag数组变为 0 0 1 1 0,统计下标3之前的1的个数为0,总逆序对数为0;
取第三大数3, flag数组变为 1 0 1 1 0,统计下标1之前的1的个数为0,总逆序对数为0;
取2,flag数组变为 1 0 1 1 1,统计下标5之前的1的个数为3,总逆序对数为3;
取1,flag数组变为 1 1 1 1 1,统计下标2之前的1的个数为1,总逆序对数为4;
结束。
为了降低找第k大数的时间复杂度,我们先用快排对n个数进行降序排列,用树状数组进行求和统计。
为了记录第k大数的位置,我们用结构体来储存数据值和下标。
示例代码如下:
// 数据输入for (int i = 1; i <= n; ++i) { scanf("%d", &num[i].val); num[i].id = i;}// 降序排列sort(num+1, num+1+n, cmp);// 找到第k大数,统计它的下标之前总共1的个数,加到ans当中,最终输出ans即为结果// 标记第k大数的位置,并向上更新树状数组,两个操作顺序不能颠倒for (int i = 1; i <= n; ++i) { ans += GetSum(num[i].id); Update(num[i].id);}
3归并排序求解:
未完待续……
- 求解逆序对数的几种方法
- 求逆序对数的两种方法
- 求解数组中逆序对的对数
- UESTC 490 Swap Game (特殊的求解逆序对数)
- UESTC 490 Swap Game (特殊的求解逆序对数)
- 逆序对数的计算
- 求逆序数的几种方法
- 字符串逆序的几种方法
- 求逆序数的几种方法
- 两种方法求解逆序对
- 求逆序数的对数
- 求数组的逆序对数
- 求解素数几种方法
- Java笔试之几种字符串逆序的方法
- C#-数字逆序输出的几种方法
- 数学总结之求逆序数的几种方法
- 逆序对数
- 逆序对数
- 四、Opencv2.4.9和Python工具包的安装
- 算法导论:第8章 线性时间排序__基数排序
- 折半插入排序
- leetcode:Merge Two Sorted Lists 【Java】
- 再谈SQL Server中日志的的作用
- 求解逆序对数的几种方法
- Android Studio上方便使用butterknife注解框架的偷懒插件Android Butterknife Zelezny
- andrAndroid 权限
- beta分布 and Dirichlet分布
- 1016 Phone Bills
- html meta标签
- std::function & Functor(用 Functor 构造std::function时的注意点)
- pthread_mutex_lock
- VC++2010工程中加入SplashScreen