题目描述

使数组唯一的最小增量
给定整数数组 A,每次 move 操作将会选择任意 A[i],并将其递增 1。

返回使 A 中的每个值都是唯一的最少操作次数。

示例 1:

输入:[1,2,2]
输出:1
解释:经过一次 move 操作,数组将变为 [1, 2, 3]。
示例 2:

输入:[3,2,1,2,1,7]
输出:6
解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
可以看出 5 次或 5 次以下的 move 操作是不能让数组的每个值唯一的。
提示:

0 <= A.length <= 40000
0 <= A[i] < 40000


解题思路

1.贪心,每次达到局部最优,最后收敛于整体最优。

  • 先对数组进行排序
  • 比较前后两个元素的大小。若后面元素小于前面元素,将后面元素递增到前面元素+1.
    时间复杂度O(nlogn),因为主要操作在于排序

2.计数排序

  • 设置一个hash表,大小为40001(数组最长为40000)
  • 先找出数组的最大值,遍历从0到最大值的hash表。若当前元素出现次数大于1,则只保留一个,其他元素全部+1,移到后一位
  • 遍历结束后,Max+1存储的出现次数往后移动,只需用求和公式计算,不必一直移动。

代码

class Solution:
    def minIncrementForUnique(self, A: List[int]) -> int:
        # A.sort()
        # res = 0
        # for i in range(1, len(A)):
        #     if A[i]<=A[i-1]:
        #         res += A[i-1]-A[i]+1
        #         A[i] = A[i-1]+1
        # return res

        # hashTable
        hashTable = [0]*40001
        Max = -1
        res = 0
        for x in A:
            hashTable[x] += 1
            Max = max(Max, x)

        for x in range(Max+1):
            if hashTable[x]>1:
                hashTable[x+1] += hashTable[x]-1
                res += hashTable[x]-1

        d = hashTable[Max+1]-1
        res += ((1+d)*d)//2
        return res