C经典程序求数组中的逆序对

需求描述

数组中的两个数字,如果前面一个数字大于后面的数字(

题目保证输入的数组中没有的相同的数字

),则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对取模的结果输出。即输出Pmod

要求:空间复杂度

O(n)O(n)

,时间复杂度

O(nlogn)O(nlogn)

测试用例

测试用例1

输入:

[1,2,3,4,5,6,7,0]

复制

返回值:

7

复制

测试用例2

输入:

[1,2,3]

复制

返回值:

代码编写思路:使用归并排序

因为我们在归并排序过程中会将数组划分成最小为1个元素的子数组,然后依次比较子数组的每个元素的大小,依次取出较小的一个合并成大的子数组。

这里我们也可以用相同的方法划分,划分之后相邻一个元素的子数组就可以根据大小统计逆序对,而不断往上合并的时候,因为已经排好序了,我们逆序对可以往上累计。我们主要有以下三个阶段。

具体做法:

step1:划分阶段:将待划分区间从中点划分成两部分,两部分进入递归继续划分,直到子数组长度为1.

step2:排序阶段:使用归并排序递归地处理子序列,同时统计逆序对,因为在归并排序中,我们会依次比较相邻两组子数组各个元素的大小,并累计遇到的逆序情况。而对排好序的两组,右边大于左边时,它大于了左边的所有子序列,基于这个性质我们可以不用每次加1来统计,减少运算次数。

step3:合并阶段:将排好序的子序列合并,同时累加逆序对。

图示:

示例代码

classSolution{

public:

intmod=;

intmergeSort(intleft,intright,vectorintdata,vectorinttemp)

{

//停止划分

if(left=right)

return0;

//取中间

intmid=(left+right)/2;

//左右划分合并

intres=mergeSort(left,mid,data,temp)+mergeSort(mid+1,right,data,temp);

//防止溢出

res%=mod;

inti=left,j=mid+1;

for(intk=left;k=right;k++)

temp[k]=data[k];

for(intk=left;k=right;k++)

{

if(i==mid+1)

data[k]=temp[j++];

elseif(j==right+1

temp[i]=temp[j])

data[k]=temp[i++];

购买专栏解锁剩余24%


转载请注明:http://www.aierlanlan.com/grrz/3559.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了