【说人话的算法小课堂】使用分治法(基于归并排序的思想)求一个排列的逆序数(O(n^2)→O(n log n))

在这里插入图片描述

分治法求逆序数

前置知识:归并排序。
我们已经证明了归并排序的正确性。只要将归并排序算法作少量修改,就可以将求一个排列的逆序数的时间复杂度从O(n^2)降低到O(n log⁡n)。
将一个排列P尽量均匀地分成两部分P_1,P_2。则P的逆序数
τ§=τ(P_1 )+τ(P_2 )+τ_Merge
显然,τ(P_1 )和τ(P_2 )分别代表递归求解的在P_1,P_2范围内的逆序数。而τ_Merge则将遗漏的情况,即构成逆序对(a_i,a_j), i<j, a_i>a_j的两个元素a_i,a_j满足a_i∈P_1,a_j∈P_2的情况全部覆盖。
归并排序的过程中,合并两个有序(升序)数列的步骤是:
设一个临时数列t,用于归并。
指针i和j分别指向两个子数列的开头。子数列的范围分别是_begin到_mid、_mid + 1到_end。
不断从两个子数列中各取一个元素(即指针i和j分别指向的元素)比较,将较小的数放到数列t中,对应的指针递增(当两个元素相等时,默认将地址较低的数组中的数,即i指向的数放入t)。当其中一个子数列取完后,该循环结束。
将没取完元素的子数列的全部元素都复制到数列t中。
设从长度分别为m,n的两个有序数列P_1,P_2中取出的两个数分别为x_i,y_j,下标代表它们在有序数列中的位置。每次比较时如果发现一次x_i>y_j,又已知序列是升序的,就有
x_k>y_j, k=i,i+1,…,m, x_k∈P_1,y_j∈P_2
也就是说找到了m-i+1个逆序对。即τ_Merge=m-i+1。
代码:

template<class _Ty> size_t merge(_Ty* _begin, _Ty* _mid, _Ty* _end) {
   
	const 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值