问题描述
小R有一组橡皮泥士兵,每个士兵的大小各不相同或非常接近。为了使每个士兵的大小都不同,小R可以通过增加某些士兵的大小来实现这一目标。每次操作可以给某个士兵加一单位橡皮泥,以增加其大小。给定士兵的数量 n 和每个士兵当前的大小的数组 a,计算为了使所有士兵的大小都不同,至少需要增加多少单位橡皮泥。
解题思路
-
理解问题:
- 我们需要确保数组
a中的所有元素都是唯一的。 - 每次操作可以将某个元素增加1,目标是使所有元素不同,并且操作次数最少。
- 我们需要确保数组
-
数据结构选择:
- 由于我们需要对数组进行排序和遍历,选择数组作为主要数据结构。
-
算法步骤:
- 排序:首先对数组
a进行排序,这样我们可以更容易地处理重复元素。 - 遍历数组更新
- 排序:首先对数组
-
初始化:
ed初始化为数组的第一个元素a[0],因为在排序后的数组中,第一个元素本身肯定是唯一的。
-
遍历数组:
- 从第二个元素开始遍历数组。
- 如果当前元素
a[i]小于或等于ed,则说明a[i]需要增加,直到它大于ed。 - 每次增加
a[i]时,ed也会相应地增加,以确保ed始终是当前已经处理过的最大元素值。
-
更新
ed:- 如果
a[i]大于ed,则直接将ed更新为a[i],因为a[i]已经是唯一的。
- 如果
-
复杂度分析:
- 时间复杂度:排序的时间复杂度为
O(n log n),遍历数组的时间复杂度为O(n),因此总的时间复杂度为O(n log n)。 - 空间复杂度:除了输入数组外,额外使用的空间为常数级别,因此空间复杂度为
O(1)。
- 时间复杂度:排序的时间复杂度为
代码实现
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int solution(int n, vector<int> a) {
sort(a.begin(), a.end());
int ed = a[0], res = 0;
for(int i = 1; i < n; i ++ ) {
if(a[i] <= ed) {
ed ++ ;
res += ed - a[i];
} else {
ed = a[i];
}
}
return res;
}
int main() {
cout << (solution(5, {1, 1, 2, 3, 3}) == 5) << endl;
cout << (solution(6, {4, 4, 4, 5, 5, 6}) == 11) << endl;
cout << (solution(7, {10, 20, 10, 30, 40, 30, 20}) == 3) << endl;
return 0;
}
代码解释
- 排序:
sort(a.begin(), a.end());对数组a进行排序。 - 遍历:从第二个元素开始遍历,如果当前元素
a[i]小于或等于前一个元素ed,则增加ed并计算需要增加的大小ed - a[i],累加到结果res中。 - 返回结果:最终返回
res,即最少需要增加的橡皮泥单位数。
测试样例
- 样例1:
n = 5, a = [1, 1, 2, 3, 3],输出5。 - 样例2:
n = 6, a = [4, 4, 4, 5, 5, 6],输出11。 - 样例3:
n = 7, a = [10, 20, 10, 30, 40, 30, 20],输出3。
通过以上步骤,我们可以有效地解决橡皮泥士兵大小调整问题,确保所有士兵的大小都不同,并且操作次数最少。