环形数组中的最大贡献值 | 豆包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

问题理解

你有一个长度为 n 的环形数组 a,需要找到两个下标 i 和 j,使得 f(i, j) = (a[i] + a[j]) * dist(i, j) 的值最大。其中 dist(i, j) 是下标 i 和 j 在数组中的最短距离。

关键点

  1. 环形数组:由于数组是环形的,最左和最右的元素也是相邻的。因此,计算距离时需要考虑两种情况:

    • j 在 i 的右边,距离为 j - i
    • j 在 i 的左边,距离为 i + n - j
  2. 贡献值公式f(i, j) = (a[i] + a[j]) * dist(i, j)

解题思路

  1. 遍历所有可能的 i 和 j 组合

    • 对于每个 i,遍历 j 从 i+1 到 n-1,j从i+1开始遍历是为了减少不必要的循环次数。
    • 计算 dist(i, j) 并更新最大贡献值。
  2. 计算距离

    • 对于每个 i 和 j,计算 dist(i, j) 为 min(j - i, i + n - j)
  3. 更新最大贡献值

    • 使用 max 函数更新当前的最大贡献值。

数据结构选择

  • 使用一个变量 res 来存储当前的最大贡献值,循环过程中更新即可。

算法步骤

  1. 初始化 res 为 0

    • 这是为了确保在第一次比较时,res 能够被正确更新。
  2. 遍历所有可能的 i 和 j 组合

    • 使用两层循环,外层循环遍历 i,内层循环遍历 j
    • 注意 j 从 i+1 开始,因为 i 和 j 不能相同。
  3. 计算 dist(i, j)

    • 对于每个 i 和 j,计算 dist(i, j) 为 min(j - i, i + n - j)
    • 这里 min 函数用于选择最短的距离。
  4. 更新最大贡献值

    • 使用 max 函数更新 res,即 res = max(res, (a[i] + a[j]) * dist(i, j))
  5. 返回 res

    • 最终返回 res,即最大贡献值。

代码如下:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int solution(int n, std::vector<int> a) {
    // write code here
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int d = min(j - i, i + n - j);
            res = max(res, (a[i] + a[j]) * d);
        }
    }
    return res; // Placeholder return
}

int main() {
    std::cout << (solution(3, {1, 2, 3}) == 5) << std::endl;
    std::cout << (solution(4, {4, 1, 2, 3}) == 12) << std::endl;
    std::cout << (solution(5, {1, 5, 3, 7, 2}) == 24) << std::endl;
    return 0;
}

image.png