剑指Offer:JZ35 - 数组中的逆序对(解题思路+Java代码)

这篇博客介绍了如何运用归并排序算法来计算数组中的逆序对数量。通过对数组进行分治,博主详细解释了在归并过程中如何统计逆序对,并通过实例展示了算法的运行过程。最后,提供了关键代码片段,展示如何在归并排序的合并步骤中计算逆序对,并对结果取模。
摘要由CSDN通过智能技术生成

JZ35-数组中的逆序对

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

输入描述:

题目保证输入的数组中没有的相同的数字数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5

示例1

输入

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

输出

7

解题思路:使用归并排序的思想,归并排序不懂点这里查看归并排序详解;本题使用归并排序举例比如[6,3,1,4],可以看成[[6,3],[1,4]],当前6比1,4大,3比1大,共有3对,排序之后[[3,6],[1,4]],3比1大,同时6也肯定比1大,接下来6比4大,也是3对,结果都是一样的。

排序的好处就是当前数比较完之后,后面的数不用和比较过的再比,一定会比之前比较过得大。

代码看这里,相对于归并排序主要修改的是32-34行,记录逆序对数量。

public class Solution {
    public int InversePairs(int [] array) {
        return mergeSort(array, 0, array.length - 1, new int[array.length]);
    }
    /**
	 * 归并排序私有的处理方法
	 * @author 枫叶火火
	 * @param arr	数组
	 * @param first	第一个坐标
	 * @param last	最后一个坐标
	 * @param temp	临时数组
	 */
    private int mergeSort(int[] arr, int first, int last, int[] temp) {
		if (first >= last) {
			return 0;
		}
        int count = 0;//保存当前统计的逆序对数量
		// 将arr看成两块
		int i = first; // 块1的第一个坐标
		int j = first + (last - first) / 2; // 块1的最后一个坐标
		int m = j + 1; // 块2的第一个坐标
		int n = last; // 块2的最后一个坐标
		int k = 0; // 临时数组坐标
		count += mergeSort(arr, i, j, temp); // 递归处理块1
		count += mergeSort(arr, m, n, temp); // 递归处理块2
		// 对有序的块1和块2进行合并
		while (i <= j && m <= n) { // 当两块数组都有值时
			if (arr[i] <= arr[m]) { // 将小的先填入临时数组
				temp[k++] = arr[i++];
			} else {
				temp[k++] = arr[m++];
                //修改归并排序,进行计数
                count += (j-i+1); //如果i已经比比较的数字大,那么i之后到j的数字也一定比当前比较的数字大
                count %= 1000000007;
			}
		}
		while (i <= j) { // 如果第1块还有剩余填入临时数组
			temp[k++] = arr[i++];
		}
		while (m <= n) { // 如果第2块还有剩余填入临时数组
			temp[k++] = arr[m++];
		}
		// 将两块数组替换成排序好的一块
		for (int ii = 0; ii < k; ii++) {
			arr[first + ii] = temp[ii];
		}
        return count;           
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值