独特橡皮泥士兵|豆包MarsCode AI刷题

58 阅读3分钟

问题描述

小R有一组橡皮泥士兵,每个士兵的大小各不相同或非常接近。为了使每个士兵的大小都不同,小R可以通过增加某些士兵的大小来实现这一目标。每次操作可以给某个士兵加一单位橡皮泥,以增加其大小。给定士兵的数量 n 和每个士兵当前的大小的数组 a,计算为了使所有士兵的大小都不同,至少需要增加多少单位橡皮泥。

解题思路

  1. 理解问题

    • 我们需要确保数组 a 中的所有元素都是唯一的。
    • 每次操作可以将某个元素增加1,目标是使所有元素不同,并且操作次数最少。
  2. 数据结构选择

    • 由于我们需要对数组进行排序和遍历,选择数组作为主要数据结构。
  3. 算法步骤

    • 排序:首先对数组 a 进行排序,这样我们可以更容易地处理重复元素。
    • 遍历数组更新
  4. 初始化

    • ed 初始化为数组的第一个元素 a[0],因为在排序后的数组中,第一个元素本身肯定是唯一的。
  5. 遍历数组

    • 从第二个元素开始遍历数组。
    • 如果当前元素 a[i] 小于或等于 ed,则说明 a[i] 需要增加,直到它大于 ed
    • 每次增加 a[i] 时,ed 也会相应地增加,以确保 ed 始终是当前已经处理过的最大元素值。
  6. 更新 ed

    • 如果 a[i] 大于 ed,则直接将 ed 更新为 a[i],因为 a[i] 已经是唯一的。
  7. 复杂度分析

    • 时间复杂度:排序的时间复杂度为 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;
}

代码解释

  1. 排序sort(a.begin(), a.end()); 对数组 a 进行排序。
  2. 遍历:从第二个元素开始遍历,如果当前元素 a[i] 小于或等于前一个元素 ed,则增加 ed 并计算需要增加的大小 ed - a[i],累加到结果 res 中。
  3. 返回结果:最终返回 res,即最少需要增加的橡皮泥单位数。

测试样例

  • 样例1n = 5, a = [1, 1, 2, 3, 3],输出 5
  • 样例2n = 6, a = [4, 4, 4, 5, 5, 6],输出 11
  • 样例3n = 7, a = [10, 20, 10, 30, 40, 30, 20],输出 3

通过以上步骤,我们可以有效地解决橡皮泥士兵大小调整问题,确保所有士兵的大小都不同,并且操作次数最少。