题目描述
给定两个长度为 N 的整数数组 A 和 B,要求找到最小的操作次数,使得数组 A 可以变成数组 B。可以进行以下两种操作:
- 反转数组 A:即将数组 A 的顺序完全颠倒。
- 修改单个元素:选择数组 A 中某个位置的元素,对其添加或减去任意值。
任务是计算最小的操作次数,其中每次操作计为 1 次。下面通过一个具体的例子来理解题目:
示例 1:
-
输入:N = 3, A = [1, 2, 5], B = [4, 2, 1]
-
输出:2
- 操作 1:反转数组 A,得到 [5, 2, 1]。
- 操作 2:对 A[0] 减去 1,得到 [4, 2, 1]。
答案是 2,因为我们用了 2 次操作。
思路解析
我们需要思考如何将数组 A 转换为数组 B。最明显的思路是可以分两步:
- 直接操作 A 到 B:不进行反转,直接修改 A 中每个元素使其变为 B 中的对应元素。
- 反转操作:先将数组 A 反转,再通过修改操作将反转后的数组转换为数组 B。
通过比较这两种方法的操作次数,我们就可以找到最小的操作次数。
操作的具体计算
为了计算操作次数,我们需要定义一个辅助函数来计算数组 A 和 B 中对应位置的不同元素个数。因为每次操作只能修改一个元素,因此两个数组中不同的元素个数就是我们所需的修改次数。
另外,反转数组的操作也需要考虑其对操作次数的影响。反转后的数组可能需要较少的修改操作,因此需要在两种方式下选择最少的操作次数。
代码实现
import java.util.Arrays;
public class Main {
// 计算将数组 A 转换为 B 的最小操作次数
public static int solution(int N, int[] A, int[] B) {
// 计算不反转的情况下的最小操作次数
int directChange = countChanges(A, B);
// 创建一个反转后的数组 A'
int[] reversedA = new int[N];
for (int i = 0; i < N; i++) {
reversedA[i] = A[N - 1 - i];
}
// 计算反转后的情况下的最小操作次数
int reversedChange = countChanges(reversedA, B);
// 返回两种情况中的最小值
return Math.min(directChange, reversedChange + 1); // 反转操作计一次
}
// 计算两个数组中不相同的位置个数
private static int countChanges(int[] A, int[] B) {
int changes = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] != B[i]) {
changes++;
}
}
return changes;
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution(3, new int[] { 1, 2, 5 }, new int[] { 4, 2, 1 }) == 2);
System.out.println(solution(4, new int[] { 7, 8, 6, 2 }, new int[] { 6, 2, 8, 7 }) == 3);
System.out.println(solution(2, new int[] { 3, 9 }, new int[] { 9, 3 }) == 1);
}
}
代码解释
solution(int N, int[] A, int[] B):这个方法用来计算最小的操作次数。首先,调用countChanges(A, B)计算不反转数组 A 的情况下,A 到 B 的最小操作次数。然后,我们将 A 数组进行反转,调用countChanges(reversedA, B)计算反转后的 A 到 B 的操作次数。最后,我们返回两种操作次数中的最小值,并且反转操作本身算作一次操作,所以结果加 1。countChanges(int[] A, int[] B):这个辅助方法用来计算数组 A 和 B 中不相同的位置的个数。因为每个不同的元素都需要进行一次修改,所以返回的就是修改次数。main方法:在主函数中,我们通过几个测试用例验证了算法的正确性。
复杂度分析
- 时间复杂度:主要的操作是在计算数组 A 和 B 的不同元素个数上,复杂度是 O(N),其中 N 是数组的长度。由于我们只进行了一次反转和两次计数,因此总的时间复杂度是 O(N)。
- 空间复杂度:由于我们额外使用了一个反转后的数组
reversedA,空间复杂度是 O(N)。
总结
这道题考察了如何通过两种操作(反转数组和修改元素)来最小化转换次数。通过暴力方法,遍历数组计算不同位置的元素个数,我们能够轻松求得最小操作次数。该问题的难点在于如何灵活使用反转操作来减少后续的修改次数,从而达到最优解。
希望通过本篇文章,能够帮助大家更好地理解如何分析问题,并通过简单的算法来解决实际问题。如果你还有任何疑问,欢迎在评论区留言。