LeetCode 945使数组唯一的最小增量
-
题目简述:给定整数数组 A,每次 move 操作将会选择任意
A[i]
,并将其递增1
。返回使A
中的每个值都是唯一的最少操作次数。 -
输入:[1,2,2] 输出:1 解释:经过一次 move 操作,数组将变为 [1, 2, 3]。
输入:[3,2,1,2,1,7] 输出:6 解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
-
思路:先排序后遍历,时间复杂度O(nlogn)
首先将数组进行排序,然后从左到右遍历数组:
- 如果当前元素大于等于上一个元素,保持不变;
- 如果当前元素小于上一个元素,就需要增加当前元素,直到大于上一个元素。
- 最后的当前数字变的至少比前面的数字大1
例如输入
[3,2,1,2,1,7]
,排序后[1, 1, 2, 2, 3, 7]
,move操作后[1, 2, 3, 4, 5, 7]
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
int n = A.size(), res = 0;
sort(A.begin(), A.end());
//排序后A[i-1]一定小于等于A[i]
for(int i = 1; i < n; i++)
{
//如果A[i-1]小于A[i]则不需要记录操作A[i]也保持不变
if(A[i-1] < A[i])
{
res += 0;
A[i] += 0;
}
//如果A[i-1]等于A[i]则需要记录操作并将A[i]更新值比原先大1
else if(A[i-1] == A[i])
{
res += 1;
A[i] += 1;
}
//在更新过程中会将排序打乱,出现A[i-1]大于A[i]的情况
else
{
res += A[i-1] - A[i] + 1;
A[i] += A[i-1] - A[i] + 1;
}
/*
if(A[i-1] >= A[i])//等价于上面的三个逻辑
{
res += A[i-1] - A[i] + 1;
A[i] += A[i-1] - A[i] + 1;
}
*/
}
return res;
}
};
//优化写法二:
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
int n = A.size(), res = 0;
sort(A.begin(), A.end());
//排序后A[i-1]一定小于等于A[i]
for(int i = 1; i < n; i++)
{
//diff表示后者需要比前者大1,所要进行的操作次数
int diff = A[i-1] - A[i] + 1;
res += max(0, diff);
A[i] += max(0, diff);
}
return res;
}
};
//优化写法三:
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
int n = A.size(), curmax = 0, res = 0;
sort(A.begin(), A.end());
for(int i = 0; i < n; i++)
{
//如果A[i]<curmax表示A[i]在前边出现过了
//需要将A;[i]增加到curmax,然后自加1
if(A[i] < curmax) res += curmax - A[i];
//否则A[i]可用,并更新curmax为A[i]+1
else curmax = A[i];
curmax++;
}
return res;
}
};
贪心+并查集解法: