【LeetCode】396-旋转函数

137 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

396-旋转函数

题目描述

给定一个长度为 n 的整数数组 nums

假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为:

F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1] 返回 F(0), F(1), ..., F(n-1)中的最大值 。

生成的测试用例让答案符合 32 位 整数。

示例

示例 1:
输入: nums = [4,3,2,6]
输出: 26
解释:
F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25
F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16
F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23
F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26
所以 F(0), F(1), F(2), F(3) 中的最大值是 F(3) = 26 。

示例 2:
输入: nums = [100]
输出: 0

提示

  • n == nums.length
  • 1 <= n <= 105
  • -100 <= nums[i] <= 100

题解

思路

在示例中

原始数组:[4,3,2,6]F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 25

旋转 1 次:[6,4,3,2]F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 16

旋转 2 次:[2,6,4,3]F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 23

旋转 3 次:[3,2,6,4]F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 26

从 F0 到 F1 的区别在于:0 * 4 变成了 1 * 41 * 3 变成了 2 * 32 * 2 变成了 3 * 23 * 6 变成了 0 * 6

从 F1 到 F2 的区别在于:0 * 6 变成了 1 * 61 * 4 变成了 2 * 42 * 3 变成了 3 * 33 * 2 变成了 0 * 2

从 F2 到 F3 的区别在于:0 * 2 变成了 1 * 21 * 6 变成了 2 * 62 * 4 变成了 3 * 43 * 3 变成了 0 * 3

这样的话就很容易看出规律了,在数组 [4,3,2,6] ,当旋转一次后变成了 [6,4,3,2],其中的 3,2,1 在原有的基础上各加一次,而 6 从 3 * 60 * 6 相当于减了 3 次,而下面的每旋转一次数组,总和都是在上一个数的基础上变化的,变化规则就是其中 nums[1] nums[n - 1] 各加一次,nums[0] 减去三次,这样虽然有规律,但是代码不好写,我们可以让 nums[0]nums[n - 1] 各加一次,然后 nums[0] 减去四次,而且减去的四次刚好就是数组的长度。

假设数组的总和为 sum,那么每旋转一次有以下规律:

F(i) = F(i - 1) + sum - nums[0] * nums.length

代码

public int maxRotateFunction(int[] nums) {
    int n = nums.length;
    int sum = 0;
    int f = 0;
    for (int i = 0; i < n; i++) {
        sum += nums[i];
        f += nums[i] * i;
    }
    int res = f;
    for (int i = n - 1; i > 0; i--) {
        f = f + sum - nums[i] * n;
        res = Math.max(res, f);
    }
    return res;
}

代码解析

首先第一轮循环将原始数组的总和 f 计算出来,并且计算出所有元素的总和 sum

然后由于是顺时针旋转,所以从数组的最后一个元素开始遍历,每次遍历的 ff + sum - nums[i] * n,然后计算出最大的总和保存到 res中返回即可。