一,题目详情
1,问题描述
小S拿到了一个长度为 n 的环形数组,并定义了两个下标 i 和 j 的贡献值公式为:f(i, j) = (a_i + a_j) × dist(i, j),其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。
例如,给定数组 [1, 2, 3],由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)×1=5。
2,测试样例
样例1:
输入:n = 3,a = [1, 2, 3]
输出:5
样例2:
输入:n = 4,a = [4, 1, 2, 3]
输出:12
样例3:
输入:n = 5,a = [1, 5, 3, 7, 2]
输出:24
二,解题思路
1,问题分析
我们需要找到环形数组中两个元素的最大贡献值,贡献值由它们的和乘以最短距离决定。环形数组的特点使得距离的计算需要考虑两种方向(顺时针和逆时针)。
2,算法策略
核心思想是:对于每个可能的距离d(从1到n//2),找到所有相距d的元素对中和最大的一对,然后计算其贡献值。最终取所有距离中的最大贡献值。
具体步骤如下:
- 初始化最大贡献值为0。
- 遍历所有可能的距离d,从1到n//2。
- 对于每个d,遍历所有起始位置i,计算其对应的j=(i+d)%n。
- 记录当前距离d下最大的元素和。
- 计算当前距离d下的最大贡献值,并更新全局最大值。
3,逐步推演(以样例2为例)
输入:n = 4,a = [4, 1, 2, 3]
距离d的可能取值为1和2。
-
当d=1时:
- i=0,j=1:4+1=5
- i=1,j=2:1+2=3
- i=2,j=3:2+3=5
- i=3,j=0:3+4=7 最大和为7,贡献值7×1=7。
-
当d=2时:
- i=0,j=2:4+2=6
- i=1,j=3:1+3=4
- i=2,j=0:2+4=6
- i=3,j=1:3+1=4 最大和为6,贡献值6×2=12。
所以最大贡献值为12。
三,代码实现
def solution(n: int, a: list) -> int:
max_val = 0
max_d = n // 2
for d in range(1, max_d + 1):
current_max = 0
for i in range(n):
j = (i + d) % n
current_max = max(current_max, a[i] + a[j])
candidate = current_max * d
if candidate > max_val:
max_val = candidate
return max_val
1,复杂度分析
-
时间复杂度:O(n^2)
- 外层循环运行n//2次,内层循环运行n次
-
空间复杂度:O(1)
- 仅使用常数级额外空间
2,边界测试
if __name__ == '__main__':
# 常规测试
print(solution(n = 3, a = [1, 2, 3]) == 5)
print(solution(n = 4, a = [4, 1, 2, 3]) == 12)
print(solution(n = 5, a = [1, 5, 3, 7, 2]) == 24)
# 边界测试:n=1
print(solution(n = 1, a = [5]) == 0)
# 边界测试:所有元素相同
print(solution(n = 4, a = [2, 2, 2, 2]) == 8)
四,总结
通过遍历所有可能的距离并计算对应的最大元素和,我们实现了:
- 找到最大贡献值:通过比较所有可能的距离和元素对
- 高效的计算:利用环形数组的特性,避免重复计算
- 普适性:适用于所有环形数组
这种解法不仅高效,还易于理解和实现。当遇到“需要在环形数组中找到最优元素对”类问题时,遍历所有可能的距离并计算对应的最大值往往是解决问题的关键策略。