剑指笔记——51.数组中的逆序对

题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,
求出这个数组中的逆序对的总数P

思路:以下是剑指中的思路。最容易想到是就是顺序扫描整个数组,每扫描到一个数字,逐个比较这个数字和它后面数字的大小。这种思路的时间复杂度是O(n^{^{2}}).剑指提供了一种比较快的思路,本质上是归并排序。我们先把数组分隔为子数组,统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对。在统计的过程中,还需要对数组进行排序。

归并排序的时间复杂度是O(nlogn),比上面提到的方法要快,但是同时归并排序需要一个长度为n的辅助数组,相当于使用O(n)的空间消耗换来了时间效率的提升,因此是一种空间换时间的算法。

 

代码:

int count = 0;
public  int InversePairs(int [] array) {
if(array==null)

return 0;
mergeSort(array,0,array.length-1);
return count;
}
public static  void mergeSort(int[] data,int start,int end) {

//分治的思想,将数组对半划分
int mid = (start + end) / 2;
if (start < end) {
mergeSort(data, start, mid);  //左边部分
mergeSort(data, mid + 1, end);  //右边部分
merge(data, start, mid, end);  //左右归并两部分
}
}

//start是左数组第一个元素的索引,mid是左数组最后一个元素的索引,mid+1是右数组第一个元素的索引,end是右数组最后一

//个元素的索引
public static void merge(int[] data,int start,int mid,int end) { 
int arr[] = new int[end - start + 1];  //创建一个辅助数组
int c = 0;  //辅助数组的指针
int s = start; //保存最开始左边数组的初始位置
int index = mid + 1;
while (start <= mid && index <= end) {
if (data[start] < data[index]) {
arr[c++] = data[start++];
} else {
arr[c++] = data[index++];
count += mid +1 - start;   //逆序对的个数为左边数组目前的长度,start为当前左数组的索引,mid为左数组的最后一个元素。
}
}

//将最后剩的那个元素添加到辅助数组中
while (start <= mid) {
arr[c++] = data[start++];
}
while (index <= end) {
arr[c++] = data[index++];
}

//将辅助数组的元素复制回原始数组
for (int d : arr) {
data[s++] = d;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值