小和
在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和累加起来,叫数组小和。
求数组小和。
例如:[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
func TestSmallSum(t *testing.T){
arr := []int{1,3,4,2,5}
fmt.Println(smallSum(arr))
}
func smallSum(arr []int) int {
if arr == nil || len(arr) < 2 {
return 0
}
return process(arr,0, len(arr) - 1)
}
func process(arr []int, l, r int) int {
if l == r {
return 0
}
mid := l + (r-l) >> 1
return process(arr,l,mid) + // 左组求小和
process(arr,mid+1,r)+ // 右组求小和
Merge(arr,l,mid,r) // 整体求小和
}
func Merge(arr []int,L, M, R int) int {
help := make([]int,R - L +1)
i, p1, p2, res := 0, L, M+1 ,0
for ;p1 <= M && p2 <= R;i++ {
if arr[p1] < arr[p2] {
res += (R - p2 + 1) * arr[p1] //Merge的时候会产生小和,产生右组元素个数个,因为右组所有数都比左组大
help[i]= arr[p1]
p1++
}else {
help[i] = arr[p2]
p2++
}
}
for p1 <= M {
help[i] = arr[p1]
i++
p1++
}
for p2 <= R {
help[i] = arr[p2]
i++
p2++
}
for i = 0; i < len(help); i++ {
arr[L+ i] = help[i]
}
return res
}