青训营X豆包MarsCode 技术训练营:环形数组中的最大贡献值Python3题解| 豆包MarsCode AI 刷题

68 阅读4分钟

环形数组中的最大贡献值

问题描述

小S拿到了一个长度为 nn 的环形数组,并定义了两个下标 ii 和 jj 的贡献值公式为:
f(i, j) = (a_i + a_j) × dist(i, j)
其中 dist(i, j) 是下标 ii 和 jj 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。

例如,给定数组 [1, 2, 3],由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)×1=5f(2,3)=(2+3)×1=5。


测试样例

样例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. 计算顺时针距离:顺时针距离是两个下标之间的直接距离。
  3. 计算逆时针距离:逆时针距离是数组长度减去顺时针距离。
  4. 选择最短距离:选择顺时针距离和逆时针距离中的较小值作为最短距离。
  5. 计算贡献值:对于每一对下标 (i, j),计算 f(i, j) 并记录最大值。
  6. 优化计算:为了避免重复计算,可以预先计算每个元素与其他元素的距离,并存储在一个矩阵中。

Python3代码(通过豆包Marscode测试)

def solution(n: int, a: list) -> int:
    # 初始化最大贡献值
    max_contribution = 0
    
    # 遍历每一对下标 (i, j)
    for i in range(n):
        for j in range(n):
            if i != j:
                # 计算顺时针距离
                dist_clockwise = abs(j - i)
                # 计算逆时针距离
                dist_counterclockwise = n - dist_clockwise
                # 选择最短距离
                dist = min(dist_clockwise, dist_counterclockwise)
                
                # 计算贡献值
                contribution = (a[i] + a[j]) * dist
                
                # 更新最大贡献值
                max_contribution = max(max_contribution, contribution)
    
    return max_contribution

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)

关键步骤解释

  1. 初始化最大贡献值:使用一个变量 max_contribution 来记录当前找到的最大贡献值。
  2. 遍历每一对下标:使用双重循环遍历所有可能的下标对 (i, j)
  3. 计算距离:对于每一对下标,计算顺时针和逆时针距离,并选择较小的那个作为最短距离。
  • 计算顺时针距离:使用 abs(j - i) 计算顺时针距离。
  • 计算逆时针距离:使用 n - dist_clockwise 计算逆时针距离。
  • 选择最短距离:使用 min(dist_clockwise, dist_counterclockwise) 选择顺时针距离和逆时针距离中的较小值。
  1. 计算贡献值:使用公式 (a[i] + a[j]) * dist 计算贡献值。
  2. 更新最大贡献值:如果当前计算的贡献值大于 max_contribution,则更新 max_contribution

时间复杂度

当前代码使用了双重循环来遍历所有可能的下标对 (i, j),并且在每次循环中计算了顺时针距离、逆时针距离以及贡献值。具体分析如下:

  1. 双重循环:外层循环和内层循环分别遍历数组的所有元素,因此总共有 n * n 次迭代。
  2. 每次迭代中的操作:每次迭代中,计算顺时针距离、逆时针距离、选择最短距离、计算贡献值以及更新最大贡献值,这些操作都是常数时间复杂度 O(1)

因此,总的时间复杂度为 O(n^2),其中 n 是数组的长度。

空间复杂度

当前代码的空间复杂度主要取决于存储变量的数量,具体分析如下:

  1. 变量存储:代码中使用了几个变量来存储最大贡献值、当前贡献值、顺时针距离、逆时针距离等,这些变量的数量是固定的,不随输入规模 n 的变化而变化。
  2. 数组 a:输入数组 a 的空间复杂度为 O(n)

因此,总的空间复杂度为 O(n),其中 n 是数组的长度。

总结

  • 时间复杂度O(n^2)
  • 空间复杂度O(n)