数据结构与算法之返回最小和问题
问题描述:
在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和累加起来,叫数组小和。求数组小和。
例子: [1,3,4,2,5]
1左边比1小的数:没有
3左边比3小的数:1
4左边比4小的数:1、3
2左边比2小的数:1
5左边比5小的数:1、3、4、 2
所以数组的小和为1+1+3+1+1+3+4+2=16
思路:
思路:利用递归实现,对于一个数组,将其任意划分为两部分,如果左部分以及右部分分别是有序的,那么统计左边任意一个数产生的小和,可以看成是求解右边有多少个数比当前数大的问题,右边某一个数A大于左边这个数B,那么A后面的数都会大于B,当统计完完右边区域的长度数目n, 就有n个小和B产生。
图示:
代码:
public class day03_MergeSmall {
public static void main(String[] args) {
int [] arr = {1,3,4,2,5};
System.out.println(mergeSmall(arr));
}
public static int mergeSmall(int [] arr){
if (arr == null || arr.length < 2){
return -1 ;
}
return process(arr,0,arr.length-1);
}
public static int process(int [] arr ,int left ,int right){
if (left == right){
return 0;
}
int mid = left + ((right-left)>>1);
return process(arr,left,mid)
+
process(arr,mid+1,right)
+
merge(arr,left,mid,right);
}
public static int merge(int [] arr,int left,int mid ,int right){
int [] help = new int[right - left + 1];
int i = 0;
int p1 = left;
int p2 = mid + 1;
int result = 0;
while(p1 <= mid && p2 <= right){
result += arr[p1] < arr[p2] ? arr[p1]*(right-p2+1):0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++]:arr[p2++];
}
while(p1 <= mid){
help[i++] = arr[p1++];
}
while(p2 <= right){
help[i++] = arr[p2++];
}
for (int j = 0; j <help.length ; j++) {
arr[left+j] = help[j];
}
return result;
}
}