使用归并思想查找数组中的逆序对的数量——Java实现

使用二分归并思想,一个数组的逆序对的数量 = (构成逆序对的数字都在左半部分)左半部分逆序对的数量 + (构成逆序对的数字都在右半部分)右半部分逆序对的数量  + (构成逆序对的数字左半部分一个,右半部分一个)左右两部分的逆序对的数量。


Java代码如下:

public class Solution {
	
	// 使用归并思想统计数组中的逆序对
	public static int invertCount(int[] nums, int left, int right) {
		if (left >= right) {
			return 0;
		}
		int middle = (left + right) / 2;
		// 整个序列的逆序数,等于左半部分的逆序数 + 右半部分的逆序数 + 左右构成的逆序数
		int leftCount = invertCount(nums, left, middle);
		int rightCount = invertCount(nums, middle + 1, right);
		int both = merge(nums, left, middle, right);
		return leftCount + rightCount + both;
	}

	// 归并过程
	public static int merge(int[] nums, int left, int middle, int right) {
		int invertNum = 0;
		// 使用两个临时数组保存元素
		int index = left;
		int length1 = middle - left + 1;
		int length2 = right - middle;
		int[] num1 = new int[length1];
		int[] num2 = new int[length2];
		for (int i = 0; i < length1; i++) {
			num1[i] = nums[index];
			index++;
		}
		for (int i = 0; i < length2; i++) {
			num2[i] = nums[index];
			index++;
		}
		index = left;
		// 归并过程
		int first = 0;
		int second = 0;
		while (first < length1 && second < length2) {
			if (num1[first] <= num2[second]) {
				nums[index] = num1[first];
				first++;
			} else {
				nums[index] = num2[second];
				second++;
				// 此时,num2中当前正处理的数字,和当前num1中的所有数字构成逆序
				invertNum += (length1 - first);
			}
			index++;
		}
		if (first == length1) {
			// 将num2剩余的数字全部赋值到nums数组中(这一过程,不需要逆序对统计工作)
			while (second < length2) {
				nums[index] = num2[second];
				second++;
				index++;
			}
		} else {
			// 将num1剩余的数字全部赋值到nums数组中(这一过程,不需要逆序对统计工作)
			while (first < length1) {
				nums[index] = num1[first];
				first++;
				index++;
			}
		}
		return invertNum;
	}

	public static void main(String[] args) {
		// 逆序对数量应为3
		int[] nums = { 3, 14, 1, 7 };
		System.out.println(Solution.invertCount(nums, 0, nums.length - 1));
		

		// 逆序对数量应为7
		int[] nums2 = { 3, 14, 1, 7, 35, 52, 4 };
		System.out.println(Solution.invertCount(nums2, 0, nums2.length - 1));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值