package basic_class_01;
/**
* 求小和问题 : 找出左边 比 右边 元素 小的所有 元素之后
* @author lenovo
*
*/
public class Code_12_SmallSum {
/**
*
*
* 求小和问题
*
*
* @param arr
* @return
*/
public static int smallSum(int[] arr) {
if(arr == null || arr.length < 2) {
return 0;
}
return mergeSort(arr, 0, arr.length - 1);
}
public static int mergeSort(int[] arr, int L, int R) {
if(L == R) {
return 0;
}
int mid = L + ((R - L) >> 1);
return mergeSort(arr, L, mid) + mergeSort(arr, mid + 1, R) + merge(arr, L, mid, R);
}
/**
* 每一个小组的小和在上一次就已经计算完成了
* 所以合并时需要计算一个更大范围里的小和
*
* @param arr
* @param L
* @param M
* @param R
* @return
*/
public static int merge(int[] arr, int L, int M, int R) {
int[] help = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
int res = 0;
/**
* 求出小和之后 需要进行排序
* 这一步排序才是关键所在,因为排序之后可以节省重复的运算
* 如果不进行排序 的话 有的小和 可能会被漏掉,而且比较的次数也变得更多
*/
while(p1 <= M && p2 <= R) {
res += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0; // (R - p2 + 1) 这个是比左边元素大的有多少个
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= M) {
help[i++] = arr[p1++];
}
while(p2 <= R) {
help[i++] = arr[p2++];
}
for(i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
return res;
}
}
好喜欢那种安静写作业的女生啊,特别美.真好,安静地看着她.