小和问题

之所以能够使用归并排序进行解决,是因为归并排序在**merge**的时候,会进行两部分的比较,例如
每次merge都可以计算出在这次merge中形成的小和,最后相加即为答案
public class xiaohe {public static void main(String[] args) {int[] array = new int[]{1,2,3};System.out.println(mergeSort(array, 0, array.length - 1));}//给数组中left到right范围的子序列做归并排序public static int mergeSort(int[] array,int left,int right) {if (left == right) {//说明这个子数组只有一个值了,一定是有序的,直接返回即可return 0;}//递归,再分子数组//先得到中间位置(mid = left + (right-left)/2)int mid = left + ((right-left) >> 1);return mergeSort(array,left,mid) +mergeSort(array,mid+1,right) +//左右子序列排好序了,现在把左右子序列做一个归并merge(array,left,mid+1,right);}//index1是左子序列的起始值//index2是有右子序列的起始值//right是右子序列的终点public static int merge(int[] array,int index1,int index2,int right) {//index1是左子序列的位置//index2是右子序列的位置int sum = 0 ;int left = index1;int[] tmp = new int[right-index1+1];int record = index2;int index = 0 ;while (index1 < record && index2<=right) {//如果左边比右边小,那左边这个数就要比右边这个数以及右边这个数还大的数小sum += array[index] < array[index2] ? (right-index2+1) * array[index1] : 0;tmp[index++] = array[index1]>=array[index2]? array[index2++]:array[index1++];}while (index1 < record) {tmp[index++] = array[index1++];}while (index2 <= right) {tmp[index++] = array[index2++];}for (int i=0;i<tmp.length;i++) {array[left+i] = tmp[i];}return sum;}}
逆序对问题

与小和问题类似,这个是求merge过程中,左侧子序列中的数比右侧子序列中的数更大的情况。
public class nixudui {public static void main(String[] args) {int[] array = new int[]{3,2,1};mergeSort(array, 0, array.length - 1);}//给数组中left到right范围的子序列做归并排序public static void mergeSort(int[] array,int left,int right) {if (left == right) {//说明这个子数组只有一个值了,一定是有序的,直接返回即可return ;}//递归,再分子数组//先得到中间位置(mid = left + (right-left)/2)int mid = left + ((right-left) >> 1);mergeSort(array,left,mid);mergeSort(array,mid+1,right);//左右子序列排好序了,现在把左右子序列做一个归并merge(array,left,mid+1,right);}//index1是左子序列的起始值//index2是有右子序列的起始值//right是右子序列的终点public static void merge(int[] array,int index1,int index2,int right) {//index1是左子序列的位置//index2是右子序列的位置int left = index1;int[] tmp = new int[right-index1+1];int record = index2;int index = 0 ;while (index1 < record && index2<=right) {//如果左边比右边大,那左边这个数和左子序列中大于左边的这个数 会与 右边的数形成逆序对if (array[index1] > array[index2]) {for (int i=index1;i<record;i++) {System.out.println("(" + array[i] + "," + array[index2] + ")");}}tmp[index++] = array[index1]>=array[index2]? array[index2++]:array[index1++];}while (index1 < record) {tmp[index++] = array[index1++];}while (index2 <= right) {tmp[index++] = array[index2++];}for (int i=0;i<tmp.length;i++) {array[left+i] = tmp[i];}}}
