【前言】坚持日更LeetCode刷题系列
已经有一段时间没有更新这个系列了,不过还是有在坚持每日打卡,写博客分享的话就视情况而定了,因为最近这段时间还在补以前的坑~~~
【题目】945.使数组唯一的最小增量
题目描述:给定整数数组 A,每次 move 操作将会选择任意 A[i]
,并将其递增 1
。
返回使 A
中的每个值都是唯一的最少操作次数。
示例:
示例 1:
输入:[1,2,2]
输出:1
解释:经过一次 move 操作,数组将变为 [1, 2, 3]。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
思路一:
开始的时候,我想到先通过排序后再对列表进行操作,但是因为考虑到列表A的长度过大,所以pass了这种方案。那么对于如何判断数值是否存在于先前操作列表,我们自然而然地会想到哈希表。
操作步骤如下:
1.采用字典作为存储结构
2.遍历整个列表,判断值是否存在于字典中,如果不存在直接将其添加字典中
3.如果存在则进行move操作,并且将move操作后的值存入字典
具体代码如下:
class Solution(object):
def minIncrementForUnique(self, A):
"""
:type A: List[int]
:rtype: int
"""
hashmap = {}
move = 0
for index,num in enumerate(A):
if num not in hashmap.values():
hashmap[index] = num
else:
while(num in hashmap.values()):
num = num + 1
move = move + 1
hashmap[index] = num
return move
运行结果:
进一步的思考:
为什么刚才的操作会出现超时错误呢?相信很多朋友都注意到了,在move操作中,由于之前数字并不是按序排列从而我们只能一次一次进行move操作,最终导致出现了超时错误。
关于其中一些知识的链接:
字典has_key()方法
思路二:
有了上一次的教训,在这次操作中,我们显然会想到先进行排序操作,从而减少move操作耗时。且对于此时我们判断数字是否存在于先前操作列表,因为已经有了排序操作,则只需要判断当前位置i与前一个位置i-1即可,因此此时我们并不需要采用字典来进行存储。
操作步骤如下:
1.在原列表上直接进行操作
2.对列表进行排序
3.遍历整个列表,判断当前位置的值与前一个位置的值之间的关系,如果当前位置值大于前一个位置值,则进入下一轮循环;如果当前值小于等于前一个位置值,则进行move操作
具体代码如下:
class Solution(object):
def minIncrementForUnique(self, A):
"""
:type A: List[int]
:rtype: int
"""
A.sort()
move = 0
for i in range(1,len(A)):
if A[i] <= A[i-1]:
move += A[i-1]-A[i]+1
A[i] = A[i-1]+1
return move
运行结果:
以下分享一些其他前辈的解题思路,例如:贪心算法、并查集、线性探测等。
其他解题思路1
其他解题思路2
分享就到这里了,欢迎大家一起交流讨论。
注明
:
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-increment-to-make-array-unique