import java.util.*; import java.lang.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static int res = 0; public static void main(String[] args) { Scanner in = new Scanner(System.in); while(in.hasNext()){ res = 0; int N = in.nextInt(); int[] arr = new int[N]; for(int i=0;i<N;i++) arr[i]=in.nextInt(); mergeSort(arr); System.out.println(res); } } public static void mergeSort(int[] arr){ if(arr.length>1){ int mid = arr.length/2; int[] left = Arrays.copyOfRange(arr,0,mid); int[] right = Arrays.copyOfRange(arr,mid,arr.length); mergeSort(left); mergeSort(right); merge(arr,left,right); } } public static void merge(int[] arr, int[] left, int[] right){ int i=0,j=0,k=0; while(i<left.length && j<right.length){ if(left[i]<=right[j]) arr[k++] = left[i++]; else { arr[k++] = right[j++]; res+=left.length-i; } } while(i<left.length) arr[k++] = left[i++]; while(j<right.length) arr[k++] = right[j++]; } }
官方题解已经有归并排序的主思路了,我看了这个题目的题解非常少,其实更加关键的问题在于:归并排序中,怎么统计交换了多少次?在哪里加代码?
我这里给出解答:在归并排序中,两个有序数组进行merge的时候,且发生了左边的元素比右边大的情况,例如:左数组为[3,4],右数组为[1,2],他们合并的时候,1和2就需要跑到3和4的前面去,这其实就是相当于1和3、4交换了2次,2再和3、4交换了2次,最终形成[1,2,3,4]。除了明确维护交换次数的时机以外,还需要明确具体交换了几次,那肯定是左边数组left剩下多少元素就交换多少次(left.length-i,其中i代表左边数组已经用过的次数,例如left = [1,3,4], right = [2],那么2其实只需要越过3、4就能到达它该呆着的地方,1在2之前就已经用过了)