
求逆序数图解(分治)--算法学习
分割数组:将数组分成两半,左半和右半。 递归计算:分别计算左半和右半的逆序数。 合并计算:计算左半和右半之间形成的逆序对的数量。 mergeSort函数:递归地将数组分成两半,调用自身进行排序,并在合并时使用mergeAndCount计算逆序对。 mergeAndCount函数:使用双指针法计算跨半的逆序对数量。左半和右半已排好序,通过比较左右指针所指元素的大小来确定逆序对的数量。 主函数:读取输入,初始化数组,调用归并排序并计算逆序数,最后输出结果。
发布日期:2021-05-15 00:27:52
浏览次数:20
分类:精选文章
本文共 1494 字,大约阅读时间需要 4 分钟。
为了计算给定排列的逆序数,我们可以使用分治法结合归并排序的方法。这种方法的时间复杂度是O(n log n),非常适合处理较大的n值(如n ≤ 100000)。
分治法的步骤
双指针法计算跨半逆序对
假设左半和右半已经排好序,使用双指针从两端开始比较:
- 左指针指向左半的开头,右指针指向右半的开头。
- 比较左右指针所指的元素:
- 如果左半的元素小于右半的元素,左指针前进。
- 否则,右指针前进,并增加逆序对的数量。
这种方法确保了每个元素只被访问一次,时间复杂度为O(n)。
代码实现
#include#include using namespace std;long long sum = 0;void mergeSort(int* arr, int s, int e, int* temp) { if (s >= e) return; int mid = s + (e - s) / 2; mergeSort(arr, s, mid, temp); mergeSort(arr, mid + 1, e, temp); mergeAndCount(arr, s, mid, e, temp);}void mergeAndCount(int* arr, int s, int mid, int e, int* temp) { int p1 = s, p2 = mid + 1; while (p1 <= mid && p2 <= e) { if (arr[p1] < arr[p2]) { temp[index++] = arr[p1++]; } else { sum += mid - p1 + 1; temp[index++] = arr[p2++]; } } while (p1 <= mid) { temp[index++] = arr[p1++]; } while (p2 <= e) { temp[index++] = arr[p2++]; }}int main() { int n; vector a(n); for (int i = 0; i < n; ++i) { cin >> a[i]; } int* temp = new int[n]; mergeSort(a.data(), 0, n-1, temp); cout << sum << endl; delete[] temp; return 0;}
代码解释
这种方法不仅高效,还通过递归和迭代的结合,确保了代码的简洁和可维护性。
发表评论
最新留言
不错!
[***.144.177.141]2025年04月20日 09时59分45秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Flask--简介
2021-05-14
16 python基础-恺撒密码
2021-05-14
Frame--Api框架
2021-05-14
Boostrap技能点整理之【网格系统】
2021-05-14
新闻发布项目——业务逻辑层(UserService)
2021-05-14
hibernate正向生成数据库表以及配置——hibernate.cfg.xml
2021-05-14
javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Dao层
2021-05-14
java实现人脸识别源码【含测试效果图】——Dao层(IUserDao)
2021-05-14
使用ueditor实现多图片上传案例——前台数据层(Index.jsp)
2021-05-14
解决Chrome播放视频闪屏黑屏无法播放
2021-05-14
Git简单理解与使用
2021-05-14
echarts 基本图表开发小结
2021-05-14
制作JS验证码(简易)
2021-05-14
adb通过USB或wifi连接手机
2021-05-14
包装类
2021-05-14
JDK9-15新特性
2021-05-14
集合继承结构
2021-05-14
LinkedList 实现类
2021-05-14