在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组得小和.
比如[1,3,4,2]1左边比1小的数没有,3左边比3小的数有1,4左边比4小的数有1,3,2左边比2小的数有1.那么这个数组的小和是
1+1+3+1=6
暴力方法是每次遍历的时候,都要再把前面的比较一下,这样时间复杂度是O(n^2)这样明显不行,仔细思考下过程,就是归并排序的过程之中,
在你进行归并的时候,你需要左边比右边小的时候记录下来,进行累加,可以算出右边有多少个数比它大,代码如下:
public static int getSmallSum(int[] a, int l, int r) { if (l >= r || a.length == 1) return 0; int mid = l + ((r - l) >> 1); //左边求小和加右边求小和加整体求整体小和 return getSmallSum(a, l, mid) + getSmallSum(a, mid + 1, r) + process(a, l, mid, r); } private static int process(int[] a, int l, int mid, int r) { int[] aux = new int[r - l + 1]; int lo = l; int hi = mid + 1; int index = 0; int sum = 0; while (lo <= mid && hi <= r) { if (a[lo] < a[hi]) { //左边只有小才能算是小和,相等不算 sum = sum + (r - hi + 1) * a[lo]; aux[index++] = a[lo++]; } else { aux[index++] = a[hi++]; } } while (lo <= mid) { aux[index++] = a[lo++]; } while (hi <= r) { aux[index++] = a[hi++]; } for (int aux1 : aux) { a[l++] = aux1; } return sum; }