题目
Given an array of integers A and let n to be its length.
Assume Bk to be an array obtained by rotating the array A k positions clock-wise, we define a “rotation function” F on A as follow:
F(k)=0∗Bk[0]+1∗Bk[1]+...+(n−1)∗Bk[n−1] .
Calculate the maximum value of F(0), F(1), …, F(n-1).
Example:
A = [4, 3, 2, 6]
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
So the maximum value of F(0), F(1), F(2), F(3) is F(3) = 26.
Note: n is guaranteed to be less than 105.
思考
如果不考虑优化,直接用两层循环来将每个F计算出来然后取最大值的话,复杂度为 O(n2) ,代码如下的第一个答案,会卡在第16个测试,超时,因此需要降低复杂度。
简化计算过程,使得计算一次F不需要一轮循环(n)。简化后的过程如下:
1. 计算F(0)
和A的所有元素的和sum
;
2. 通过F(0)
计算F(A.size()-1)
:F(0) - sum + A[0] * A.size()
;
3. 与步骤2类似,通过F(A.size()-1)
计算F(A.size()-2)
,直到F(1)
。
用这种方法的复杂度为 O(2n) 。
例子具体步骤如下表格:其中加粗的为 F(i), i = 0, A.size() - 1, A.size() - 2, ..., 1
A = [4, 3, 2, 6]
系数 | 4 | 3 | 2 | 6 | 和 |
---|---|---|---|---|---|
last | 0 | 1 | 2 | 3 | 25 |
-sum2 | -1 | 0 | 1 | 2 | 10 |
+ A[0] * A.size() | 3 | 0 | 1 | 2 | 26 |
-sum2 | 2 | -1 | 0 | 1 | 11 |
+ A[1] * A.size() | 2 | 3 | 0 | 1 | 23 |
… |
Q:为什么F(0)的下一个不是F(1)?
A:也可以按F(0),F(1)的顺序计算,只需要将- sum + A[i] * A.size()
变成+ sum - A[i] * A.size()
,并且将A从尾开始遍历即可。
答案
c++
两层循环:
class Solution {
public:
int maxRotateFunction(vector<int>& A) {
int length = A.size();
if (length == 0) return 0;
int max = -2147483648;
for (int i = 0; i < length; i++) {
int temp = 0;
for (int j = i, k = 0; k < length; k++, j = (j + 1) % length) {
temp += k * A[j];
}
if (temp > max) max = temp;
}
return max;
}
};
一层循环:
class Solution {
public:
int maxRotateFunction(vector<int>& A) {
int length = A.size();
if (length == 0) return 0;
int max = 0; // result
int sum = 0; // sum of A's elements
for (int i = 0; i < length; i++) {
max += i * A[i]; // F(0)
sum += A[i];
}
int last = max; // last F
for (int i = 0; i < length - 1; i++) {
last -= sum;
last += A[i] * length;
max = last > max ? last : max;
}
return max;
}
};