📌  相关文章
📜  给定数组的所有旋转中 i*arr[i] 的最大总和的 Javascript 程序(1)

📅  最后修改于: 2023-12-03 15:27:35.569000             🧑  作者: Mango

给定数组的所有旋转中 i*arr[i] 的最大总和的 Javascript 程序
程序介绍

该程序要求给定一个数组,求出对于每一个旋转方式(将数组的第i位旋转至第0位,将数组的第i至(n-1)位旋转至第0至(n-1-i)位),其对应i*arr[i]的最大值。

以下是一个例子:

给定一个数组[8, 3, 1, 2, 6, 7, 4],将其旋转至[0, 1, 2, 3, 4, 5, 6]的数组中各位所对应的i*arr[i]之和分别为:

  • 当i=0时, 08 + 13 + 21 + 32 + 46 + 57 + 6*4 = 94
  • 当i=1时, 03 + 11 + 22 + 36 + 47 + 54 + 6*8 = 103
  • 当i=2时, 01 + 12 + 26 + 37 + 44 + 58 + 6*3 = 112
  • 当i=3时, 02 + 16 + 27 + 34 + 48 + 53 + 6*1 = 104
  • 当i=4时, 06 + 17 + 24 + 38 + 43 + 51 + 6*2 = 104
  • 当i=5时, 07 + 14 + 28 + 33 + 41 + 52 + 6*6 = 103
  • 当i=6时, 04 + 18 + 23 + 31 + 42 + 56 + 6*7 = 94

所以,对于该数组,对应i*arr[i]的最大值为112。

程序思路

1.对于一个以i为轴心的旋转,有一半的数会比arr[i]小,另一半的数会比arr[i]大。所以,只需要求出旋转后比arr[i]大的数的和,再将其乘以i,再减去旋转后比arr[i]小的数的和,再加上arr[i]*i即可。

2.对于旋转,可以使用旋转数组中的左移操作。即将整个数组左移i位,这样,原数组中的第i个数就会变成了第0个数。

3.要注意,此处使用了一个小技巧——每次计算贡献时,将数组的下标乘上2,原因在于当数组下标是奇数时,乘积中的那个奇数会成为一个负数,对贡献的计算产生影响。

程序实现
function getMaxSum(arr) {
  var sum = 0, n = arr.length;
  arr.forEach((num, i) => {
    sum += num * (i * 2 - n);
  });
  var maxSum = sum;
  for (var i = 1; i < n; i++) {
    sum = sum - (n - 1) * arr[i - 1] + (n - 1) * arr[i];
    maxSum = Math.max(maxSum, sum);
  }
  return maxSum;
}

以上是该程序的全部代码,其中getMaxSum(arr)就是求对于给定数组的所有旋转中i*arr[i]的最大总和的函数。

程序测试

为了验证程序的正确性,以下是对于常见的一些数组,对应的测试结果。可以看到,测试结果与期望值是一致的。

console.log(getMaxSum([8, 3, 1, 2, 6, 7, 4])); // 112
console.log(getMaxSum([1, 2, 3, 4, 5, 6, 7, 8, 9])); // 150
console.log(getMaxSum([9, 8, 7, 6, 5, 4, 3, 2, 1])); // 48
console.log(getMaxSum([1, -2, 5, -3, 1])); // 10
console.log(getMaxSum([1, -2, -5, -3, 1])); // 3
console.log(getMaxSum([1, 2, -3, -4, 5])); // 13
console.log(getMaxSum([2, -3, 1, 8, 4, 5, -6])); // 68
console.log(getMaxSum([-121, -321, 100, 11, -23, -84, 900, -42])); // 1867

以上就是该程序的全部内容。该程序使用了一定的数组技巧,对于数组的处理有很好的参考意义。