问题描述
小C有两个长度为 N
的数组 A
和 B
。他可以进行以下两种操作,来将数组 A
转换为数组 B
:
- 反转数组
A
,即使数组A
的元素顺序完全颠倒。 - 在
[1, N]
范围内选择一个整数i
,然后可以对A[i]
添加或减去任意值。
你的任务是帮助小C找到使数组 A
等于数组 B
所需的最小操作次数。
例如:当 N = 3
,A = [1, 2, 5]
,B = [4, 2, 1]
时,最佳操作如下:
- 第一步反转数组
A
,得到新数组A = [5, 2, 1]
。 - 第二步从位置
1
减去1
,得到新数组A = [4, 2, 1]
。
因此,答案是2
。
问题理解
我们需要将数组 A
转换为数组 B
,允许的操作有两种:
- 反转数组
A
。 - 对数组
A
中的任意元素进行加减操作。
目标是找到最小的操作次数,使得数组 A
变为数组 B
。
算法步骤
-
初始化:定义一个函数
solution
,接收参数N
、A
和B
。 -
直接比较:
- 遍历数组
A
和数组B
,逐个元素比较。 - 如果
A[i]
不等于B[i]
,则需要进行一次调整操作。 - 统计需要调整的元素个数,记为
count_no_reverse
。
- 遍历数组
-
反转比较:
- 反转数组
A
,得到新的数组A_reversed
。 - 遍历数组
A_reversed
和数组B
,逐个元素比较。 - 如果
A_reversed[i]
不等于B[i]
,则需要进行一次调整操作。 - 统计需要调整的元素个数,并加上一次反转操作的次数(1次),记为
count_reverse
。
- 反转数组
-
比较结果:
- 比较
count_no_reverse
和count_reverse
。 - 选择操作次数较小的那个作为最终结果。
- 比较
代码实现
def solution(N: int, A: list, B: list) -> int:
count_no_reverse = 0
for i in range(N):
if A[i] != B[i]:
count_no_reverse += 1
count_reverse = 1 # 反转操作本身算一次操作
A_reversed = A[::-1]
for i in range(N):
if A_reversed[i] != B[i]:
count_reverse += 1
return min(count_no_reverse, count_reverse)
关键步骤注释
- 直接比较:在
count_no_reverse
中,我们直接遍历数组A
和数组B
,计算需要调整的元素个数。 - 反转比较:在
count_reverse
中,我们先反转数组A
,然后再次遍历数组A
和数组B
,计算需要调整的元素个数。 - 比较结果:通过
min(count_no_reverse, count_reverse)
返回两种情况中操作次数较小的那个。
时间复杂度
-
直接比较:
- 遍历数组
A
和数组B
,逐个元素比较。 - 这一步的时间复杂度是
O(N)
,其中N
是数组的长度。
- 遍历数组
-
反转比较:
- 反转数组
A
,得到新的数组A_reversed
。 - 反转操作的时间复杂度是
O(N)
。 - 遍历数组
A_reversed
和数组B
,逐个元素比较。 - 这一步的时间复杂度也是
O(N)
。
- 反转数组
-
比较结果:
- 比较
count_no_reverse
和count_reverse
。 - 这一步的时间复杂度是
O(1)
。
- 比较
综合以上步骤,总的时间复杂度是 O(N)
。
空间复杂度
-
直接比较:
- 只需要常数空间来存储
count_no_reverse
。 - 空间复杂度是
O(1)
。
- 只需要常数空间来存储
-
反转比较:
- 需要额外的空间来存储反转后的数组
A_reversed
。 - 这一步的空间复杂度是
O(N)
。
- 需要额外的空间来存储反转后的数组
-
比较结果:
- 只需要常数空间来存储
count_reverse
。 - 空间复杂度是
O(1)
。
- 只需要常数空间来存储
综合以上步骤,总的空间复杂度是 O(N)
。
总结
- 时间复杂度:
O(N)
- 空间复杂度:
O(N)