环形数组中的最大贡献值

205 阅读4分钟

题干如下:

小S拿到了一个长度为 nn 的环形数组,并定义了两个下标 iijj 的贡献值公式为: f(i,j)=(a_i + a_jx dist(i,i)其中 dist(i,j)是下标iiii 在数组中的最短距离。小S希望找到一对下标,使得它们的贡献值尽可能大。环形数组的特点是最左和最右的元素也是相邻的。你需要帮助她找到最大贡献值。 例如,给定数组[1,2,31,由于是环形数组,任意两个下标的距离都是1,因此 f(2,3)=(2+3)x1=5f(2,3)=(2+ 3)x1= 5

解题思路:

  1. 初始化最大贡献值变量

    • let maxContribution = -Infinity; 这行代码定义了一个变量 maxContribution,并将其初始化为负无穷大。这么做的原因是,在开始遍历计算所有下标对的贡献值之前,我们不知道最大贡献值是多少,将其初始化为一个极小的值(在 JavaScript 中用 -Infinity 表示负无穷大),可以确保后续计算出的任何贡献值都能与其比较并在必要时更新它,使得 maxContribution 始终记录当前找到的最大贡献值。
  2. 双层 for 循环遍历下标对

    • 外层 for 循环 for (let i = 0; i < n; i++) 用于控制第一个下标 i 的取值,它从 0 开始,每次递增 1,直到 i 的值达到数组长度 n - 1。这个循环会遍历环形数组中所有可能作为第一个下标的位置。
    • 内层 for 循环 for (let j = 0; j < n; j++) 用于控制第二个下标 j 的取值,同样从 0 开始,每次递增 1,直到 j 的值达到数组长度 n - 1。对于外层循环每确定的一个 i 值,内层循环都会完整地遍历一遍所有可能的 j 值,这样就实现了对环形数组中所有下标对 (i, j) 的遍历。
  3. 计算下标对的最短距离 dist

    • let dist = Math.min(Math.abs(i - j), n - Math.abs(i - j)); 这行代码用于计算下标 i 和 j 在环形数组中的最短距离。
    • Math.abs(i - j) 计算的是按照正常顺序(非环形考虑)下标 i 和 j 的距离的绝对值,比如 i = 1j = 3,那么 Math.abs(1 - 3) = 2
    • 然而,在环形数组中,还存在另一种情况,就是从数组末尾绕到开头的距离更短。例如,对于长度为 5 的环形数组,当 i = 0j = 3 时,正常顺序距离是 3,但从环形角度考虑,跨越数组边界的距离是 5 - 3 = 2,这种情况下 n - Math.abs(i - j) 就表示跨越边界的距离(n 是数组长度)。通过 Math.min 函数取这两种距离(正常顺序距离和跨越边界距离)中的较小值,就能得到环形数组中两个下标之间的最短距离 dist
  4. 计算当前下标对的贡献值 contribution

    • let contribution = (a[i] + a[j]) * dist; 这行代码根据给定的贡献值计算公式 f(i, j) = (a[i] + a[j]) * dist(i, j) 来计算当前下标对 (i, j) 的贡献值。其中 a[i] 和 a[j] 分别是环形数组中对应下标位置的元素值,通过索引数组 a 来获取,然后将这两个元素值相加后再乘以前面计算得到的最短距离 dist,就得到了当前下标对的贡献值 contribution
  5. 更新最大贡献值 maxContribution

    • maxContribution = Math.max(maxContribution, contribution); 这行代码将当前计算得到的贡献值 contribution 和已经记录的最大贡献值 maxContribution 进行比较。Math.max 函数会返回两个值中的较大值,所以如果 contribution 比 maxContribution 更大,就会将 maxContribution 更新为 contribution 的值,从而保证 maxContribution 始终记录着到目前为止遍历过程中找到的最大贡献值。
  6. 返回最大贡献值

    • 在双层 for 循环结束后,maxContribution 变量中存储的就是整个环形数组所有下标对中最大的贡献值了,最后通过 return maxContribution; 将这个最大贡献值返回。
function solution(n, a) {
    let maxContribution = -Infinity;
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            let dist = Math.min(Math.abs(i - j), n - Math.abs(i - j));
            let contribution = (a[i] + a[j]) * dist;
            maxContribution = Math.max(maxContribution, contribution);
        }
    }
    return maxContribution;
}

function main() {
    console.log(solution(3, [1, 2, 3]) === 5);
    console.log(solution(4, [4, 1, 2, 3]) === 12);
    console.log(solution(5, [1, 5, 3, 7, 2]) === 24);
}

main();