def solution(n: int, x: int, y: int, a: list) -> int:
# 检查是否已经有逆序对
has_inversion = False
for i in range(n - 1):
if a[i] > a[i + 1]:
return 0 # 已经有逆序对
# 如果所有元素相同,至少需要1次操作
if len(set(a)) == 1:
return 1
# 检查可以通过减少或增加元素得到逆序对
min_operations = float('inf')
# 对于每一对相邻元素 a[i] 和 a[i+1]
for i in range(n - 1):
if a[i] < a[i + 1]:
# 选取操作来制造逆序对
# 1. 减少 a[i + 1]
reduce_cost = (a[i + 1] - a[i]) // y + 1
# 2. 增加 a[i]
increase_cost = (a[i + 1] - a[i] + x - 1) // x
min_operations = min(min_operations, min(reduce_cost, increase_cost))
return min_operations
if name == 'main':
print(solution(3, 1, 2, [1, 3, 5]) == 2)
print(solution(4, 5, 7, [4, 6, 10, 9]) == 0)
print(solution(5, 3, 2, [7, 7, 7, 7, 7]) == 1)
代码分析
函数定义:
solution(n: int, x: int, y: int, a: list) -> int:接受四个参数,分别是数组长度 n、增加操作的步长 x、减少操作的步长 y 和数组 a。
检查是否已经有逆序对:
遍历数组 a,如果发现相邻的两个元素 a[i] 和 a[i + 1] 满足 a[i] > a[i + 1],则说明数组中已经有逆序对,直接返回 0。
检查所有元素是否相同:
使用 set(a) 来获取数组 a 的所有唯一元素,如果 len(set(a)) == 1,说明所有元素相同,至少需要 1 次操作来打破这个顺序,返回 1。
计算最小操作次数:
初始化 min_operations 为无穷大。
遍历数组 a 中的相邻元素 a[i] 和 a[i + 1],如果 a[i] < a[i + 1],则计算使 a[i] 和 a[i + 1] 形成逆序对所需的最小操作次数。
reduce_cost:通过减少 a[i + 1] 的值来形成逆序对,计算需要的操作次数。
increase_cost:通过增加 a[i] 的值来形成逆序对,计算需要的操作次数。
更新 min_operations 为 reduce_cost 和 increase_cost 中的较小值。
返回结果:
返回计算得到的最小操作次数 min_operations。
思路分析
预处理:
首先检查数组 a 是否已经包含逆序对,如果包含则无需任何操作,直接返回 0。
检查数组 a 是否所有元素相同,如果相同则至少需要 1 次操作来打破顺序。
计算最小操作次数:
遍历数组 a 中的相邻元素对,只关注那些满足 a[i] < a[i + 1] 的元素对,因为它们是唯一可能通过操作形成逆序对的元素对。
对于每一对这样的元素,分别计算通过减少 a[i + 1] 或增加 a[i] 来形成逆序对所需的操作次数。
使用整除运算符 // 来计算操作次数,因为每次操作有一定的步长(x 或 y),所以必须向上取整(通过加 1 实现)。
复杂度分析:
遍历数组两次,时间复杂度为 O(n),其中 n 是数组 a 的长度。
空间复杂度为 O(1),因为除了输入参数和几个变量外,没有使用额外的空间。
边界条件:
考虑了数组已经包含逆序对的情况。
考虑了所有元素相同的情况。
通过整除和取余操作,正确处理了步长和操作次数的计算。