版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SIMPLE1995/article/details/86515108
一、问题
在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序对。
二、解析
如果前一篇小和问题能够理解,那么这个逆序对问题也就可以迎刃而解了。两个问题其实差不多,只不过换了种说法。
三、代码
package algorithm;
/*
*2019年1月11日
*/
public class Code_Inverse {
public static int res = 0;
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
codeInverse(arr, 0, arr.length - 1);
}
private static void codeInverse(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = l + ((r - l) >> 1);
codeInverse(arr, l, mid);
codeInverse(arr, mid + 1, r);
merge(arr, l, mid, r);
}
private static void merge(int[] arr, int l, int mid, int r) {
int[] help = new int[r - l + 1];
int p1 = l;
int p2 = mid + 1;
int i = 0;
while (p1 <= mid && p2 <= r) {
//若左边区域所指向数字大于右边区域所指向数字 则两者构成逆序对 打印之
if (arr[p1] > arr[p2]) {
//统计逆序对个数 因为左右皆有序 所以当出现一个大于左边所指数字时 右边数字后面所有数字皆可构成逆序对
res += mid - p1 + 1;
for(int j = p1; j<= mid ; j++){
System.out.print(arr[j] + " " + arr[p2] + "|");//打印逆序对
}
}
//常规归并操作 不理解参考归并排序一文
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
}
// for test
public static void main(String[] args) {
int[] test = {3,1,5,0,2,3};
mergeSort(test);
System.out.println("逆序对的个数:"+ res);
}
}
四、补充
大家如果也看了前面的博文,大致可以看到算法之路从0起步,并且一文套一文。 大家应该也发现了归并排序,小和问题,包括本文逆序对问题。三个问题代码基本一模一样。对,这就是相同类似思想问题的同一种解决方案,算法并不是固定的求解问题,而是求解一类问题。这三个问题可以通过分治思想来做,只有过最后所求不同。希望像我一样初学算法的同学也可以从中有所体会。