题目:
给你一个整数数组 nums **,按要求返回一个新数组 counts **。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
算法:
方法一:有序数组+二分查找
从右往左遍历nums,每遍历到一个数val,从有序数组array中查找小于val的元素个数,然后将val插入array中。
该方法会超时。
func countSmaller(nums []int) []int {
array := make([]int, len(nums))
ans := make([]int, len(nums))
maxPos := 0
var insert func(array []int, index, val int)
insert = func(array []int, index, val int) {
for i := maxPos - 1; i >= index + 1; i -- {
array[i] = array[i - 1]
}
array[index] = val
}
for i := len(nums) - 1; i >= 0; i -- {
pos := find(array, nums[i], 0, maxPos)
ans[i] = pos
maxPos ++
// fmt.Println("insert val:",nums[i], "right:", maxPos, "pos:", pos, array)
insert(array, pos, nums[i])
}
return ans
}
// 找到第一个大于等于val的位置
func find(sortedArray []int, val, left, right int) int {
for left < right {
mid := (left + right) / 2
if sortedArray[mid] < val {
left = mid + 1
} else {
if mid == left || mid != left && sortedArray[mid - 1] < val {
return mid
} else {
right = mid - 1
}
}
}
return right
}
方法二: 归并排序
func countSmaller(nums []int) []int {
ans := make([]int, len(nums))
array := make([][]int, len(nums))
for i := range nums {
array[i] = []int{nums[i], i}
}
var mergeSort func(numsIndex [][]int, left, right int)
mergeSort = func(numsIndex [][]int, left, right int){
if left >= right {
return
}
// tmp是逆序存储的
tmp := make([][]int, 0)
mid := left + (right - left) / 2
mergeSort(numsIndex, left, mid)
// fmt.Println("sort", left, mid, numsIndex)
mergeSort(numsIndex, mid + 1, right)
// fmt.Println("sort", mid + 1, right, numsIndex)
leftPos, rightPos := mid, right
for leftPos >= left && rightPos >= mid + 1 {
if numsIndex[leftPos][0] > numsIndex[rightPos][0] {
ans[numsIndex[leftPos][1]] = ans[numsIndex[leftPos][1]] + rightPos - (mid + 1) + 1
tmp = append(tmp, numsIndex[leftPos])
leftPos --
} else {
tmp = append(tmp, numsIndex[rightPos])
rightPos --
}
}
for leftPos >= left {
tmp = append(tmp, numsIndex[leftPos])
leftPos --
}
for rightPos >= mid + 1 {
tmp = append(tmp, numsIndex[rightPos])
rightPos --
}
// tmp是逆序存储的
for index := 0; index < len(tmp); index ++ {
numsIndex[right - index] = tmp[index]
}
}
mergeSort(array, 0, len(nums) - 1)
return ans
}
方法三:树状数组
func reversePairs(nums []int) int {
tmp := make([]int, len(nums))
copy(tmp, nums)
sort.Ints(tmp)
// 离散化, nums保存的新值是旧值的相对大小(即排序后的索引+1)
for i := range nums {
nums[i] = sort.SearchInts(tmp, nums[i]) + 1
}
biTree := binaryIndexTree{tree:make([]int, len(nums) + 1), n: len(nums)}
ans := 0
// 从右往左遍历nums,小于nums[i]的数会在bitree的左侧
for i := len(nums) - 1; i >=0; i -- {
ans = ans + biTree.query(nums[i] - 1)
biTree.update(nums[i])
}
return ans
}
type binaryIndexTree struct {
tree []int
n int
}
// lowbit找到最低位的1.
// lowbit的值相同,则在binary index tree的同一层
func (b binaryIndexTree) lowbit(x int) int {
return x & -x
}
func (b binaryIndexTree) query(x int) int {
ans := 0
// [5](0110)-[1]lowbit(5) = 4
// ans加上离散值为5的数的个数
// [4](0100)-[4]lowbit(4) = 0
// ans加上离散值小于等于4的数的个数
for x > 0 {
ans = ans + b.tree[x]
x = x - b.lowbit(x)
}
return ans
}
func (b binaryIndexTree) update(x int) {
for x <= b.n {
b.tree[x] ++
x = x + b.lowbit(x)
}
}