0396-旋转函数

Raphael Liu Lv10

给定一个长度为 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

方法一:迭代

思路

记数组 nums 的元素之和为 numSum。根据公式,可以得到:

  • $F(0) = 0 \times \textit{nums}[0] + 1 \times \textit{nums}[1] + \ldots + (n-1) \times \textit{nums}[n-1]$
  • $F(1) = 1 \times \textit{nums}[0] + 2 \times \textit{nums}[1] + \ldots + 0 \times \textit{nums}[n-1] = F(0) + \textit{numSum} - n \times \textit{nums}[n-1]$

更一般地,当 $1 \le k \lt n$ 时,$F(k) = F(k-1) + \textit{numSum} - n \times \textit{nums}[n-k]$。我们可以不停迭代计算出不同的 $F(k)$,并求出最大值。

代码

[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
class Solution:
def maxRotateFunction(self, nums: List[int]) -> int:
f, n, numSum = 0, len(nums), sum(nums)
for i, num in enumerate(nums):
f += i * num
res = f
for i in range(n - 1, 0, -1):
f = f + numSum - n * nums[i]
res = max(res, f)
return res
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int maxRotateFunction(int[] nums) {
int f = 0, n = nums.length, numSum = Arrays.stream(nums).sum();
for (int i = 0; i < n; i++) {
f += i * nums[i];
}
int res = f;
for (int i = n - 1; i > 0; i--) {
f += numSum - n * nums[i];
res = Math.max(res, f);
}
return res;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Solution {
public int MaxRotateFunction(int[] nums) {
int f = 0, n = nums.Length, numSum = nums.Sum();
for (int i = 0; i < n; i++) {
f += i * nums[i];
}
int res = f;
for (int i = n - 1; i > 0; i--) {
f += numSum - n * nums[i];
res = Math.Max(res, f);
}
return res;
}
}
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int maxRotateFunction(vector<int>& nums) {
int f = 0, n = nums.size();
int numSum = accumulate(nums.begin(), nums.end(), 0);
for (int i = 0; i < n; i++) {
f += i * nums[i];
}
int res = f;
for (int i = n - 1; i > 0; i--) {
f += numSum - n * nums[i];
res = max(res, f);
}
return res;
}
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int maxRotateFunction(int* nums, int numsSize){
int f = 0, numSum = 0;
for (int i = 0; i < numsSize; i++) {
f += i * nums[i];
numSum += nums[i];
}
int res = f;
for (int i = numsSize - 1; i > 0; i--) {
f += numSum - numsSize * nums[i];
res = MAX(res, f);
}
return res;
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
var maxRotateFunction = function(nums) {
let f = 0, n = nums.length, numSum = _.sum(nums);
for (let i = 0; i < n; i++) {
f += i * nums[i];
}
let res = f;
for (let i = n - 1; i > 0; i--) {
f += numSum - n * nums[i];
res = Math.max(res, f);
}
return res;
};
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func maxRotateFunction(nums []int) int {
numSum := 0
for _, v := range nums {
numSum += v
}
f := 0
for i, num := range nums {
f += i * num
}
ans := f
for i := len(nums) - 1; i > 0; i-- {
f += numSum - len(nums)*nums[i]
ans = max(ans, f)
}
return ans
}

func max(a, b int) int {
if b > a {
return b
}
return a
}

复杂度分析

  • 时间复杂度:$O(n)$,其中 $n$ 是数组 nums 的长度。计算 numSum 和第一个 $f$ 消耗 $O(n)$ 时间,后续迭代 $n-1$ 次 $f$ 消耗 $O(n)$ 时间。

  • 空间复杂度:$O(1)$。仅使用常数空间。

 Comments
On this page
0396-旋转函数