今天我们将在豆包MarsCode AI刷题平台上,完成《数组操作次数计算》与《最小移动次数使数组相等》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《数组操作次数计算》题面如下:
问题理解
题目要求我们对一个数组进行一系列操作,直到数组为空。每次操作的规则如下:
- 如果数组的第一个元素
a[0]等于0,则直接删除a[0],并将数组中剩余的所有元素向左移动以填补空缺。 - 否则,将
a[0]个a[0]-1添加到数组末尾,并将a[0]减少1。
我们需要计算总共进行了多少次操作,结果需要取模。
问题关键
本题的元素排列顺序对最终结果没有影响,因此对于特定元素操作次数只与元素值有关,并且是唯一的、可以由前一个元素的操作次数递推而来
数据结构的选择
使用了一个 map<int, int> 来存储每个元素的操作次数
算法步骤
- 预处理操作次数:通过一个
map来存储每个元素的操作次数,计算了由1到数组中最大元素maxval的所有元素的操作次数,并将其存储在cache中。 - 计算总操作次数:遍历数组中的每个元素,将其对应的操作次数累加到
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;
}
《最小移动次数使数组相等》题面如下:
问题理解
我们需要通过两种操作将数组 A 转换为数组 B:
- 反转数组
A。 - 对数组
A中的任意元素进行加减操作。
目标是找到最小的操作次数,本题的关键点就在于反转数组这个操作最多只会进行一次,所以我们分两种情况讨论:不翻转数组和翻转一次数组
算法步骤
-
初始化操作次数:
ret0表示不反转数组A时的操作次数。ret1表示反转数组A后的操作次数。
-
遍历数组:
- 对于每个位置
i,计算A[i]和B[i]之间的差值addOrSub0,以及A[i]和B[N-1-i]之间的差值addOrSub1。 - 如果
addOrSub0大于 0,说明需要进行加减操作,ret0加 1。 - 如果
addOrSub1大于 0,说明需要进行加减操作,ret1加 1。
- 对于每个位置
-
返回最小操作次数:
- 比较
ret0和ret1,返回较小的值。
- 比较
具体实现
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给大家展示更多题目的解法。