环形数组中的最大贡献值(青训营X豆包MarsCode) | 豆包MarsCode AI 刷题

92 阅读3分钟

问题描述

小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

要解决这个问题,我们需要找到环形数组中的一对下标 (i) 和 (j),使得它们的贡献值 (f(i, j) = (a_i + a_j) * {dist}(i, j)) 最大。其中,{dist}(i, j) 是下标 i j 在数组中的最短距离。

思路

  1. 计算最短距离
    • 对于环形数组,下标 (i) 和 (j) 之间的最短距离可以通过以下方式计算:

{dist}(i, j) = min(|i - j|, n - |i - j|)

-   这是因为环形数组中,最短距离要么是直接的距离,要么是绕过数组另一端的距离。

2. 枚举所有可能的下标对

    • 我们需要枚举所有可能的下标对 ((i, j)),并计算它们的贡献值。
    • 由于数组是环形的,我们需要考虑所有可能的下标对,包括跨越数组两端的情况。
  1. 优化计算
    • 直接枚举所有可能的下标对的时间复杂度是 (O(n^2)),对于较大的 (n) 可能会超时。
    • 我们可以考虑使用前缀和和后缀和来优化计算,但在这个问题中,直接枚举所有可能的下标对已经足够高效。

代码实现

def max_contribution(n, a):
    max_contrib = 0
    
    for i in range(n):
        for j in range(n):
            if i != j:
                dist = min(abs(i - j), n - abs(i - j))
                contrib = (a[i] + a[j]) * dist
                max_contrib = max(max_contrib, contrib)
    
    return max_contrib

# 测试样例
print(max_contribution(3, [1, 2, 3]))  # 输出:5
print(max_contribution(4, [4, 1, 2, 3]))  # 输出:12
print(max_contribution(5, [1, 5, 3, 7, 2]))  # 输出:24

解释

  1. 计算最短距离
    • dist = min(abs(i - j), n - abs(i - j)) 计算下标 (i) 和 (j) 之间的最短距离。
  1. 计算贡献值
    • contrib = (a[i] + a[j]) * dist 计算下标 (i) 和 (j) 的贡献值。
  1. 更新最大贡献值
    • max_contrib = max(max_contrib, contrib) 更新最大贡献值。
  1. 返回结果
    • 最后返回最大贡献值 max_contrib

时间复杂度

  • 直接枚举所有可能的下标对的时间复杂度是 (O(n^2))。
  • 对于较小的 (n),这个复杂度是可以接受的。如果 (n) 较大,可以考虑进一步优化,例如使用滑动窗口或动态规划等方法。但对于大多数实际应用场景,直接枚举已经足够高效。