剑指offer (35)

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

思路 : 经典的归并排序的分治思想

public class Solution {
	public static void main(String[] args) {
		int [] array = {2,1,4,3,5,1};
		Solution solution = new Solution();
		System.out.println(solution.inversePairs(array));
	}
	//统计逆序对的个数
	int cnt;
	public int inversePairs(int [] array) {
		if (array.length != 0) {
			divide(array, 0, array.length-1);
		}
		return cnt;
	}
	//归并排序的分
	public void divide(int [] arr,int start ,int end) {
		//递归的终止条件
		if (start >= end) {
			return;
		}
		//计算出中间值,注意溢出
		int mid = start + (end - start)/2;
		
		//递归分
		divide(arr, start, mid);
		divide(arr, mid+1, end);
		
		//递归的治
		merge(arr, start, mid, end);
	}
	public void merge (int []arr,int start, int mid, int end) {
		int [] temp = new int [end - start +1];
		//存一下变量
		int i = start ,j = mid + 1,k = 0;
		//下面就进行两两比较,若前面的数大于后面的数,就构成逆序对
		while (i <= mid && j <= end) {
			//若前面小于后面,直接存进去,并且移动前面数所在的数组的指针即可
			if (arr[i] <= arr[j]) {
				temp[k++] = arr[i++];
			} else {
				temp[k++] = arr[j++];
				//a[i]>a[j]了,那么这一次,从a[i]开始到a[mid]必定都是大于这个a[j]的
				//因此此时分治的两边已经是各自有序的了
				cnt = (cnt + mid - i + 1)%1000000007;
			}
		}
		//各自还有剩余的没比完,直接赋值即可
		while (i <= mid) {
			temp[k++] = arr[i++];
		}
		while (j <= end) {
			temp[k++] = arr[j++];
		}
		//覆盖原
		for (int k2 = 0; k2 < temp.length; k2++) {
			arr[start+ k2] = temp[k2];
		}
	}
}

发布了50 篇原创文章 · 获赞 0 · 访问量 393

猜你喜欢

转载自blog.csdn.net/weixin_46108108/article/details/104202609