在一个数组中,任何一个前面的数a,和任何一个后面的数b,如果(a,b)是降序的,就称为逆序对。返回逆序对个数。
1.归并排序,从右往左,相等拷右。有代码。
2.归并排序模板。有代码。
代码用golang编写,代码如下:
package main
import "fmt"
func main() {
if true {
arr := []int{3, 1, 7, 0, 2}
ret := reverPairNumber1(arr)
fmt.Println("1.从右往左,相等拷右:", ret)
}
if true {
arr := []int{3, 1, 7, 0, 2}
ret := reverPairNumber2(arr)
fmt.Println("2.归并排序模板:", ret)
}
}
func reverPairNumber1(arr []int) int {
arrLen := len(arr)
if arrLen <= 1 {
return 0
}
return process1(arr, 0, arrLen-1)
}
func process1(arr []int, L int, R int) int {
curLen := R - L + 1
if curLen <= 1 {
return 0
}
//求中点
M := L + (R-L)>>1
return process1(arr, L, M) + process1(arr, M+1, R) + merge1(arr, L, M, R)
}
func merge1(arr []int, L int, M int, R int) int {
//辅助数组
help := make([]int, R-L+1)
i := R - L + 1 - 1
p1 := M
p2 := R
res := 0
//谁小拷谁,相等拷右
for p1 >= L && p2 >= M+1 {
if arr[p1] > arr[p2] {
res += p2 - M
help[i] = arr[p1]
p1--
} else {
help[i] = arr[p2]
p2--
}
i--
}
for p1 >= L {
help[i] = arr[p1]
p1--
i--
}
for p2 >= M+1 {
help[i] = arr[p2]
p2--
i--
}
//辅助数组拷贝到原数组
copy(arr[L:R+1], help)
return res
}
func reverPairNumber2(arr []int) int {
arrLen := len(arr)
if arrLen <= 1 {
return 0
}
return process2(arr, 0, arrLen-1)
}
func process2(arr []int, L int, R int) int {
curLen := R - L + 1
if curLen <= 1 {
return 0
}
//求中点
M := L + (R-L)>>1
return process2(arr, L, M) + process2(arr, M+1, R) + merge2(arr, L, M, R)
}
func merge2(arr []int, L int, M int, R int) int {
//新增的代码
ans := 0
windowR := M + 1
for i := L; i <= M; i++ {
for windowR <= R && arr[i] > arr[windowR] {
windowR++
}
ans += windowR - M - 1
}
//辅助数组
help := make([]int, R-L+1)
i := 0
p1 := L
p2 := M + 1
//谁小拷贝谁
for p1 <= M && p2 <= R {
if arr[p1] <= arr[p2] {
help[i] = arr[p1]
p1++
} else {
help[i] = arr[p2]
p2++
}
i++
}
for p1 <= M {
help[i] = arr[p1]
p1++
i++
}
for p2 <= R {
help[i] = arr[p2]
p2++
i++
}
//辅助数组拷贝到原数组
copy(arr[L:R+1], help)
return ans
}
执行结果如下: