思路一:并查集 O(n),并查集复杂度接近O(1)
findfather(i)为i-1要变到的数字,将i修改为findfather(i)后,将father[i]和father[i]+1进行合并。
class Solution {
public:
int father[1000005];
int findfather(int n) {
if (father[n] == n) return n;
return father[n] = findfather(father[n]);
}
void uion(int u, int v) {
int fau = findfather(u);
int fav = findfather(v);
if (fau != fav) father[fau] = fav;
}
int minIncrementForUnique(vector<int>& nums) {
int ans = 0;
for (int i = 0; i < 1000005; ++i) father[i] = i;
for (auto& each : nums) {
ans += findfather(each) - each;
uion(father[each], father[each] + 1);
}
return ans;
}
};
注意:10^5 + 10^5最多到200000,所以定义father时定义到200005就可以了,而不用到10的6次方
思路二:递推 O(n)
统计出每个数字出现的个数,然后从小到大往后推,比如:1 1 1 2 2 3 ->1 2 2 2 2 3 ->1 2 3 3 3 3。
实现细节:遇到cnt[i]>1,后面个数cnt[i+1] += cnt[i] - 1 ans += cnt[i] - 1 cnt[i]=1
class Solution {
public:
int minIncrementForUnique(vector<int>& nums) {
long long cnt[200005] = {0};
for (auto& each : nums) {
cnt[each]++;
}
int index = *min_element(nums.begin(), nums.end()), ans = 0;
for (int i = index; i < 200005; ++i) {
if (cnt[i] > 1) {
ans += cnt[i] - 1;
cnt[i + 1] += cnt[i] - 1;
cnt[i] = 1;
}
}
return ans;
}
};
思路三:排序 O(nlogn)
排序后,如果当前的数字小于等于前面的数字,则赋值为前面的数字+1
class Solution {
public:
int minIncrementForUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size(), ans = 0;
for (int i = 1; i < n; ++i) {
if (nums[i] <= nums[i - 1]) {
ans += nums[i - 1] + 1 - nums[i];
nums[i] = nums[i - 1] + 1;
}
}
return ans;
}
};