c语言讲两个数组合并_求取一维数组中的逆序数

本篇内容组成:

  • 什么是逆序数
  • 求一维数组中逆序数的基本方法
  • 采用归并排序的改良版求取逆序数

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

我们将他拆分为两部分,分别叫做L和R:

bf5c6b0e77e87b34c0a6e7d51aa5d7fb.png

那么原来数组的逆序数,就可以从三个部分来求:

L部分的逆序数,R部分的逆序数,两者组合过程中的逆序数。我们在对L和R排序,并求出L和R的逆序数分别是1和1。

下面还是按照归并排序的思路进行组合两个分组。

8145fbda6869451cc598c7e1226fd39f.png

先是比较;两个分组的第一个元素,可以看出,R的首元素要小于L的首元素,那么,我们可以知道,L中的元素,任意一个都比R第一个元素1要大,而L来自于原数组左侧,R来自于原数组右侧,也就是说,每一个L中的元素,与1都是一个逆序,1的逆序数,与L中的元素的个数直接相等。(注意,只有在第一个元素比较,且左侧的大于右侧的时候,才成立)。

那这样我们就可以求出,对于这个数组,他的逆序数是1+1+3+3+2=10

00c5402a847636865c76d75c914a4620.png

把这个原理扩大一下,放到我们的归并排序中,就有了我们本次的算法:

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,伪代码就完成了,详细代码只需要稍加改动就好,今天的分享就到这儿。

我是进林,喜欢编程,希望与你共同进步,欢迎大家关注我。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值