在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。
举例:[1,4,5,3,7]
1,左边比它小数没有
4,左边比它小数:1
5,左边比它小的数:1,4
3,左边比它小的数:1
7,左边比它小的数:1,4,5,3
小和为:20
代码实现:
public static void main(String[] args) {
int[] arr = new int[]{1, 4, 5, 3, 7};
int sum = smallSum(arr);
System.out.println("小和为:"+sum);
}
public static int smallSum(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return process(arr, 0, arr.length - 1);
}
// arr[L..R]既要排好序,也要求小和返回
// 所有merge时,产生的小和,累加
// 左 排序 merge
// 右 排序 merge
// merge
public static int process(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r - l) >> 2);
//分左边
int lTotal = process(arr, l, mid);
//分右边
int rTotal = process(arr, mid + 1, r);
int mTotal = merge(arr, l, mid, r);
return lTotal + rTotal + mTotal;
}
public static int merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];
int lpos = l;
int rpos = m + 1;
int i = 0;
int result = 0;
while (lpos <= m && rpos <= r) {
result += arr[lpos] < arr[rpos] ? (r - rpos + 1) * arr[lpos] : 0;
help[i++] = arr[lpos] < arr[rpos] ? arr[lpos++] : arr[rpos++];
}
while (lpos <= m) {
help[i++] = arr[lpos++];
}
while (rpos <= r) {
help[i++] = arr[rpos++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
return result;
}
结果为: