You are given an integer array nums
. In one move, you can pick an index i
where 0 <= i < nums.length
and increment nums[i]
by 1
.
Return the minimum number of moves to make every value in nums
unique.
The test cases are generated so that the answer fits in a 32-bit integer.
Example 1:
Input: nums = [1,2,2] Output: 1 Explanation: After 1 move, the array could be [1, 2, 3].
Example 2:
Input: nums = [3,2,1,2,1,7] Output: 6 Explanation: After 6 moves, the array could be [3, 4, 1, 2, 5, 7]. It can be shown that it is impossible for the array to have all unique values with 5 or less moves.
Constraints:
1 <= nums.length <= 105
0 <= nums[i] <= 105
This problem asks for the minimum number of moves needed to make all elements in an array unique by incrementing elements. Two efficient solutions are presented: Sorting + Greedy and Counting + Greedy.
This approach leverages sorting to simplify the process of making elements unique.
Algorithm:
Sort the array: Sort the input array nums
in ascending order. This ensures we process elements from smallest to largest.
Iterate and track maximum: Initialize a variable y
to -1 (representing the highest value seen so far). Iterate through the sorted array. For each element x
:
y
to the maximum of y + 1
and x
. This ensures that the current element will be at least y + 1
after potential increments.y - x
to the total increment count (ans
). This represents the number of increments needed to make x
unique.Return the total: After iterating through all elements, ans
holds the minimum number of increments.
Time Complexity: O(n log n) due to the sorting step. The iteration is O(n).
Space Complexity: O(log n) if an in-place sorting algorithm is used. Otherwise, O(n) for some sorting algorithms.
This approach utilizes a counting array to efficiently track element frequencies and perform the necessary increments.
Algorithm:
Determine maximum possible value: Calculate m = max(nums) + len(nums)
. This represents the maximum value an element could have after all increments.
Count occurrences: Create a counting array cnt
of size m
initialized to zeros. Iterate through nums
and increment cnt[x]
for each element x
.
Iterate and increment: Iterate through cnt
from index 0 up to m - 1
. For each index i
:
cnt[i] > 1
, it means there are duplicate values of i
. Increment cnt[i+1]
by cnt[i] - 1
(number of extra occurrences) to shift those duplicates to the next higher value. Add cnt[i] - 1
to ans
to account for the number of increments performed.Return total increments: ans
contains the total minimum increments.
Time Complexity: O(m), where m = max(nums) + len(nums). In the worst case, m could be large compared to n, making this potentially less efficient than the sorting approach if the maximum value in nums
is significantly larger than the length of nums
.
Space Complexity: O(m) to store the counting array.
Code Examples (Python):
Solution 1 (Sorting + Greedy):
class Solution:
def minIncrementForUnique(self, nums: List[int]) -> int:
nums.sort()
ans = 0
y = -1
for x in nums:
y = max(y + 1, x)
ans += y - x
return ans
Solution 2 (Counting + Greedy):
from collections import Counter
class Solution:
def minIncrementForUnique(self, nums: List[int]) -> int:
m = max(nums) + len(nums)
cnt = Counter(nums)
ans = 0
for i in range(m):
if cnt[i] > 1:
diff = cnt[i] - 1
cnt[i+1] += diff #shift duplicates
ans += diff #add increments
return ans
Both solutions achieve the same result, but their efficiency depends on the characteristics of the input array (the range of values versus the number of elements). The sorting approach is generally preferred for its better average-case time complexity unless the maximum value in the input array is extremely large.