解题思路
先将数组排序,之后比较前后两个数字。
如果后面数字小于等于前面数字,则对后面数字进行 move 操作,并记录次数。
个人感觉通过排序解题不符合这道题 中等 的难度...所以尝试不排序
遍历数组A,记录每个数字出现的次数(ns)和所有数字中的最小值(min)和最大值(max)。
从最小值min开始遍历ns,将出现次数大于1的数字依次向后move ,并记录每次move的次数。
由于题中定义A中数字的区间为[0, 40000],所以在[min(max, 40001), +∞]的区间中不会有重复,可以通过求和公式直接计算。
完整代码
排序
func MinIncrementForUnique(A []int) int {
sort.Ints(A)
l := len(A)
n := 0
for i := 1; i < l; i++ {
if A[i] <= A[i-1] {
m := A[i-1] - A[i] + 1
A[i] += m
n += m
}
}
计数
// IntMax 32位最大有符号整数
const IntMax = 1<<31 - 1
// IntMin 32位最小有符号整数
const IntMin = ^IntMax
func minIncrementForUnique(A []int) int {
if len(A) == 0 {
return 0
}
ns := [40001]int{}
// ns := map[int]int{}
max := IntMin
min := IntMax
for _, n := range A {
ns[n]++
if n > max {
max = n
}
if n < min {
min = n
}
}
move := 0
for i := min; i <= max; i++ {
if ns[i] > 1 {
n := ns[i] - 1
move += n
ns[i+1] += n
}
}
n := ns[max+1] - 1
move += (1 + n) * n / 2
return move
}