标题:数组中的逆序对

题目:有一组数,对于其中任意两个数字,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法计算给定数组中的逆序对个数。

题目分析:
首先要知道什么是逆序对,比如在数组[1,2,3,4,5,6,7,0]中,逆序对有:{1,0}、{2,0}、{3,0}、{4,0}、{5,0}、{6,0}、{7,0}七个逆序对。

方法一:最好想的办法就是扫描整个数组,每扫描到一个数字的时候,就将这个数字和它后面的数字一个个进行比较,看是否比它小,比它小这两个数字就组成一个逆序对,这个方法的缺点是扫描到的每一个数都要和它后面的每一个数字比较,时间复杂度为O(n^2),不符合题目要求的高效率。

方法二:采用分治的思想,先分后治,利用归并排序来求解。
先把长度为4的数组分解成两个长度为2的子数组,再把这两个子数组分别拆成两个长度为1的子数组。接下来一边合并相邻的子数组,一边统计逆序对的数目。

1)如果数组为空null或数组长度n==0,逆序对数为0;
2)如果数组不为空,开始分割数组
3)如果数组左边下标不等于右边下标,分成两个数组。定义mid
4)如果数组左边下标等于右边下标,无法再分割,分割结束。(递归终止条件)
5)当分割成两个数组时,逆序对数=左边数组中的逆序对数+右边数组中的逆序对数+左右合并成新数组中的逆序对数
6)在一个数组中计算逆序对数时,先定义一个临时数组(用来存放有序的最终数组)
7)当left>mid+1时,说明left+1,left+2…都>mid+1;
8)返回计数器。

代码示例:

public class Main{
public int count(int[] A,int n){
if(A==null||n==0){
return 0;
}
return mergeSortsion(A,0,n-1);
}
public static int mergeSortsion(int[] a,int l,int r){
if(l==r){
return 0;
}
int mid=(l+r)/2;
return mergeSortsion(a,l,mid)+mergeSortsion(a,mid+1,r)+merge(a,l,mid,r);
}
public static int merge(int[] a,int left,int mid,int right){
int[] temp=new int[right-left+1];
int i=left;
int j=mid+1;
int index=0;
int invserseNum=0;
while(i<=mid&&j<=right){
if(a[i]<=a[j]){
temp[index++]=a[i++];
}else{
invserseNum+=mid+1-i;
temp[index++]=a[j++];
}
}
while(i<=mid){
temp[index++]=a[i++];
}
while(j<=right){
temp[index++]=a[j++];
for(int k=0;k<temp.length;k++){
a[left++]=temp[k];
}
return inverseNum;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值