本篇内容组成:
- 什么是逆序数
- 求一维数组中逆序数的基本方法
- 采用归并排序的改良版求取逆序数
NO.1,什么是逆序数:
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
举个例子,比如数组【1,2,3,4,5,6】,顺序与数字大小相一致,整体上是一个升序排列,那它的逆序数就是0,不存在逆序,如果调换了里面的数字,比如2和5,原来的数组就变为【1,5,3,4,2,6】,由于5>3,5>4,同时5>2,那5的位置引发的逆序数就是3(右侧有三个数字小于本身),数字3的逆序数为1,数字4 的逆序数是1,那么这个一维排布的数组的逆序数就是5。
我们接下来就是想要去通过程序来计算一个一维数组中的逆序数。
NO.2,求逆序数的基本方法:
容易想到的最最最简单的一个求取方法就是双重循环。
数组
但是很明显可以感觉到,这个求法,有点过于简单了,时间复杂度接近n方,不是我们想要的排序方式,于是就有了我们的利用归并排序的变体来求取。
NO.3,采用归并排序的改良版求取逆序数:
上上次我们提过快速排序的一个方案,归并排序,有点遗忘的朋友可以点击这里。
我们这里也再次将归并排序进行回顾。
归并排序方法的主要思路是这样的,先拆分,后组合,在组合的过程总完成排序。拆封过程中,最终会拆分至元素级别,这样,在组合的过程中,只需要每次比较切分后数组的前两个元素,就可以完成归并排序了。
那这样想,如果我们在合并的时候,每次左边的数字大于右边的数字,这个时候,是不是就是说明存在一个逆序呢?我们是不是只要统计合并过程中的逆序数就可以回答今天的答案了?
为了更加直观,我们来举个例子:
现在要求数组[ 5 3 6 2 1 4 ]的逆序数:
![e87c4455bb366d004e3c9c25f25a0bf6.png](https://i-blog.csdnimg.cn/blog_migrate/f801f8c888893cab874f23651a44a76a.jpeg)
我们将他拆分为两部分,分别叫做L和R:
![bf5c6b0e77e87b34c0a6e7d51aa5d7fb.png](https://i-blog.csdnimg.cn/blog_migrate/7b9baee6a0984d6dca5684ac449cb449.png)
那么原来数组的逆序数,就可以从三个部分来求:
L部分的逆序数,R部分的逆序数,两者组合过程中的逆序数。我们在对L和R排序,并求出L和R的逆序数分别是1和1。
下面还是按照归并排序的思路进行组合两个分组。
![8145fbda6869451cc598c7e1226fd39f.png](https://i-blog.csdnimg.cn/blog_migrate/d06f13089561564c6011169f7a3f5756.jpeg)
先是比较;两个分组的第一个元素,可以看出,R的首元素要小于L的首元素,那么,我们可以知道,L中的元素,任意一个都比R第一个元素1要大,而L来自于原数组左侧,R来自于原数组右侧,也就是说,每一个L中的元素,与1都是一个逆序,1的逆序数,与L中的元素的个数直接相等。(注意,只有在第一个元素比较,且左侧的大于右侧的时候,才成立)。
那这样我们就可以求出,对于这个数组,他的逆序数是1+1+3+3+2=10
![00c5402a847636865c76d75c914a4620.png](https://i-blog.csdnimg.cn/blog_migrate/af14f4101f737ab53fed99a197bc0692.jpeg)
把这个原理扩大一下,放到我们的归并排序中,就有了我们本次的算法:
merge(A,left,mind,right)cnt = 0
n1 = mid - left;
n2 = right = mid;
生成L[0,....n1],R[0.....n2]
for i = 0 to n1-1
L[1] = A[left+i]
for i = 0to m2-1
R[i] = A[mid +i]
i = 0
j = 0
for k = left = to right -1
if L[i] <= R[i]
A[k] = l[i]
i++
else
A[k] = R[i]
cnt = n1-i
j++
mergeSort(A,left,right)
if left+q <right
mid = (left + right)/2
mergeSort(A,left,right)
mergeSort(A,mid,right)
merge(A,left,mid,right)
ok,伪代码就完成了,详细代码只需要稍加改动就好,今天的分享就到这儿。
我是进林,喜欢编程,希望与你共同进步,欢迎大家关注我。