环形数组中最大贡献值的计算问题

66 阅读4分钟

环形数组中最大贡献值的计算问题

问题描述

给定一个长度为 n 的环形数组 a,我们的目标是找到一对下标 (i, j),使得它们的贡献值最大。贡献值的计算公式如下:

[ f(i, j) = (a[i] + a[j]) \times \text{dist}(i, j) ]

其中,dist(i, j) 表示数组中下标 i 和下标 j 之间的最短距离。由于数组是环形的,因此 dist(i, j) 的计算需要考虑顺时针和逆时针两种路径。

思路解析

在处理此问题时,我们需要考虑以下几点:

  1. 环形数组的特点: 由于数组是环形的,即数组的最后一个元素与第一个元素相邻,因此在计算两下标间的距离时,不仅要考虑线性距离,还要考虑绕过数组一圈的距离。

  2. 最短距离的计算: 对于任意两个下标 ij,最短距离 dist(i, j) 可以通过两种方式计算:

    • 线性距离|i - j|
    • 环形距离n - |i - j|

    因此,dist(i, j) 应该取上述两者的最小值: [ \text{dist}(i, j) = \min(|i - j|, n - |i - j|) ]

  3. 贡献值的计算: 对于每一对下标 (i, j),贡献值 f(i, j) 的计算公式为: [ f(i, j) = (a[i] + a[j]) \times \text{dist}(i, j) ]

    我们需要找到所有可能的 (i, j) 组合中最大的贡献值。

解决方案

为了求解这个问题,我们可以使用以下步骤:

  1. 遍历所有可能的 (i, j): 我们可以通过嵌套的循环,遍历所有可能的 ij,计算每一对下标的贡献值。

  2. 计算最短距离: 对于每对 (i, j),计算它们之间的最短距离 dist(i, j)

  3. 更新最大贡献值: 计算每对下标的贡献值后,更新当前的最大贡献值。

算法实现

def solution(n: int, a: list) -> int:
    max_contribution = 0
    
    # 遍历所有的 i 和 j
    for i in range(n):
        for j in range(i + 1, n):  # 确保 i < j,避免重复计算
            # 计算最短距离
            dist = min(abs(i - j), n - abs(i - j))
            # 计算贡献值
            contribution = (a[i] + a[j]) * dist
            # 更新最大贡献值
            max_contribution = max(max_contribution, contribution)
    
    return max_contribution

# 测试样例
if __name__ == '__main__':
    print(solution(3, [1, 2, 3]))  # 输出: 5
    print(solution(4, [4, 1, 2, 3]))  # 输出: 12
    print(solution(5, [1, 5, 3, 7, 2]))  # 输出: 24

代码解释

  1. 输入参数: 函数 solution(n, a) 接收两个参数:n 表示数组的长度,a 是长度为 n 的环形数组。

  2. 遍历所有 (i, j): 使用两个嵌套的 for 循环遍历所有可能的下标对 (i, j)。由于我们只需要计算一次每对 (i, j),因此内层循环从 i + 1 开始。

  3. 计算最短距离: 对于每一对 (i, j),我们首先计算它们之间的线性距离 |i - j|,然后通过 n - |i - j| 计算环形距离,最终取这两者的最小值作为 dist(i, j)

  4. 计算贡献值: 对于每一对 (i, j),我们计算它们的贡献值 f(i, j) = (a[i] + a[j]) * dist(i, j)

  5. 更新最大贡献值: 在计算每对下标的贡献值时,我们不断更新当前的最大贡献值 max_contribution

  6. 返回最大贡献值: 最后,返回所有计算中得到的最大贡献值。

复杂度分析

  • 时间复杂度:由于我们需要遍历所有可能的 (i, j) 对,并且每次计算贡献值的时间复杂度为常数 O(1),因此总的时间复杂度为 O(n^2)。对于较小的 n,这个复杂度是可以接受的。

  • 空间复杂度:算法只使用了常数空间来存储变量,因此空间复杂度是 O(1)

测试用例

  1. 输入n = 3, a = [1, 2, 3]

    • dist(0, 1) = 1, 贡献值为 (1 + 2) * 1 = 3
    • dist(0, 2) = 2, 贡献值为 (1 + 3) * 2 = 8
    • dist(1, 2) = 1, 贡献值为 (2 + 3) * 1 = 5
    • 最大贡献值为 8
  2. 输入n = 4, a = [4, 1, 2, 3]

    • dist(0, 1) = 1, 贡献值为 (4 + 1) * 1 = 5
    • dist(0, 2) = 2, 贡献值为 (4 + 2) * 2 = 12
    • dist(0, 3) = 3, 贡献值为 (4 + 3) * 3 = 21
    • dist(1, 2) = 1, 贡献值为 (1 + 2) * 1 = 3
    • dist(1, 3) = 2, 贡献值为 (1 + 3) * 2 = 8
    • dist(2, 3) = 1, 贡献值为 (2 + 3) * 1 = 5
    • 最大贡献值为 21
  3. 输入n = 5, a = [1, 5, 3, 7, 2]

    • 计算所有的贡献值后,最大贡献值为 24

总结

在环形数组中计算最大贡献值的问题可以通过暴力遍历所有可能的 (i, j) 对来解决。通过巧妙地计算最短距离并优化贡献值的计算,我们能够高效地找到最大贡献值。尽管这个方法的时间复杂度是 O(n^2),但对于小规模数据,算法仍然能够在合理的时间内给出正确答案。