《数组操作次数计算》和《最小移动次数使数组相等》| 豆包MarsCode AI刷题

145 阅读3分钟

今天我们将在豆包MarsCode AI刷题平台上,完成《数组操作次数计算》与《最小移动次数使数组相等》这两个算法问题,通过这些练习提升用户解决此类问题的能力

《数组操作次数计算》题面如下:

image.png

问题理解

题目要求我们对一个数组进行一系列操作,直到数组为空。每次操作的规则如下:

  1. 如果数组的第一个元素 a[0] 等于0,则直接删除 a[0],并将数组中剩余的所有元素向左移动以填补空缺。
  2. 否则,将 a[0]a[0]-1 添加到数组末尾,并将 a[0] 减少1。

我们需要计算总共进行了多少次操作,结果需要取模。

问题关键

本题的元素排列顺序对最终结果没有影响,因此对于特定元素操作次数只与元素值有关,并且是唯一的、可以由前一个元素的操作次数递推而来

数据结构的选择

使用了一个 map<int, int> 来存储每个元素的操作次数

算法步骤

  1. 预处理操作次数:通过一个 map 来存储每个元素的操作次数,计算了由 1 到数组中最大元素 maxval 的所有元素的操作次数,并将其存储在 cache 中。
  2. 计算总操作次数:遍历数组中的每个元素,将其对应的操作次数累加到 ret 中,并对结果取模。

具体实现

int mod = 1e9+7;
int solution(int n, std::vector<int> a) {
    // write code here
    int ret=0;
    int maxval = *max_element(a.begin(), a.end());
    map<int,int> cache;
    cache[1] = 3;
    for(int i=2;i<=maxval;i++){
        cache[i] = ((long long)cache[i-1] * (i+1) + 1) % mod;
    }
    for(int i : a){
        ret = (ret + cache[i]) % mod;
    }
    return ret;
}

《最小移动次数使数组相等》题面如下:

image.png

问题理解

我们需要通过两种操作将数组 A 转换为数组 B

  1. 反转数组 A
  2. 对数组 A 中的任意元素进行加减操作。

目标是找到最小的操作次数,本题的关键点就在于反转数组这个操作最多只会进行一次,所以我们分两种情况讨论:不翻转数组和翻转一次数组

算法步骤

  1. 初始化操作次数

    • ret0 表示不反转数组 A 时的操作次数。
    • ret1 表示反转数组 A 后的操作次数。
  2. 遍历数组

    • 对于每个位置 i,计算 A[i]B[i] 之间的差值 addOrSub0,以及 A[i]B[N-1-i] 之间的差值 addOrSub1
    • 如果 addOrSub0 大于 0,说明需要进行加减操作,ret0 加 1。
    • 如果 addOrSub1 大于 0,说明需要进行加减操作,ret1 加 1。
  3. 返回最小操作次数

    • 比较 ret0ret1,返回较小的值。

具体实现

int solution(int N, std::vector<int>& A, std::vector<int>& B) {
    int ret0 = 0, ret1 = 1; // ret1 初始为 1,因为反转操作需要一次
    for (int i = 0; i < N; i++) {
        int addOrSub0 = abs(A[i] - B[i]), addOrSub1 = abs(A[i] - B[N - 1 - i]);
        ret0 += addOrSub0 > 0;
        ret1 += addOrSub1 > 0;
    }
    return min(ret0, ret1);
}

借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《数组操作次数计算》和《最小移动次数使数组相等》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法。