http://bookshadow.com/weblog/2016/09/11/leetcode-rotate-function/
https://discuss.leetcode.com/topic/58459/java-o-n-solution-with-explanation
https://discuss.leetcode.com/topic/58302/java-solution
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).
Note:
n is guaranteed to be less than 105.
n is guaranteed to be less than 105.
Example:
https://www.cnblogs.com/grandyang/p/5869791.html
博主写了个O(n2)的方法并不能通过OJ的大数据集合,后来网上看大家的解法都是很好的找到了规律,可以在O(n)时间内完成。现在想想找规律的能力真的挺重要,比如之前那道Elimination Game也靠找规律,而用傻方法肯定超时,然后博主发现自己脑子不够活,很难想到正确的方法,说出来全是泪啊T.T。好了,来解题吧,我们为了找规律,先把具体的数字抽象为A,B,C,D,那么我们可以得到:
F(0) = 0A + 1B + 2C +3D
F(1) = 0D + 1A + 2B +3C
F(2) = 0C + 1D + 2A +3B
F(3) = 0B + 1C + 2D +3A
那么,我们通过仔细观察,我们可以得出下面的规律:
sum = 1A + 1B + 1C + 1D
F(1) = F(0) + sum - 4D
F(2) = F(1) + sum - 4C
F(3) = F(2) + sum - 4B
那么我们就找到规律了, F(i) = F(i-1) + sum - n*A[n-i],可以写出代码如下
https://discuss.leetcode.com/topic/58459/java-o-n-solution-with-explanation
F(k) = 0 * Bk[0] + 1 * Bk[1] + ... + (n-1) * Bk[n-1]
F(k-1) = 0 * Bk-1[0] + 1 * Bk-1[1] + ... + (n-1) * Bk-1[n-1]
       = 0 * Bk[1] + 1 * Bk[2] + ... + (n-2) * Bk[n-1] + (n-1) * Bk[0]
Then,
F(k) - F(k-1) = Bk[1] + Bk[2] + ... + Bk[n-1] + (1-n)Bk[0]
              = (Bk[0] + ... + Bk[n-1]) - nBk[0]
              = sum - nBk[0]
Thus,
F(k) = F(k-1) + sum - nBk[0]
What is Bk[0]?
k = 0; B[0] = A[0];
k = 1; B[0] = A[len-1];
k = 2; B[0] = A[len-2];
...
int allSum = 0;
int len = A.length;
int F = 0;
for (int i = 0; i < len; i++) {
    F += i * A[i];
    allSum += A[i];
}
int max = F;
for (int i = len - 1; i >= 1; i--) {
    F = F + allSum - len * A[i];
    max = Math.max(F, max);
}
return max;   
I think the above deductions may have some flaws. Because we cannot get the 
the base case,
F(0) from F(k). Personally I would use onlythe base case,
k = 0F(0) = 0 * Bk[0] + 1 * Bk[1] + ... + (n - 1) * Bk[n - 1]
and the case when 
k > 0 and k < nF(k) = 0 * Bk[n - k] + 1 * Bk[n - k + 1] + ... + (n - 1) * Bk[n - (k + 1)]
For those who got confused why we will start from 
i = len - 1:F(1) = F(0) + sum - n * A[n - 1], here n = len so that A[n - 1] == A[i]
F(2) = F(1) + sum - n * A[n - 2]
...
F(k) = F(k - 1) + sum - n * A[n - k]
Why we will end if 
https://discuss.leetcode.com/topic/58616/java-solution-o-n-with-non-mathametical-explainationi < 1? It's because we deduced k < n and k > 0. So that it's obviousn - k > 0, which means i > 0.    public int maxRotateFunction(int[] A) {
        int sumA = 0; int prevRotationSum = 0;
        for (int i = 0; i < A.length; i++) {
            sumA += A[i];
            prevRotationSum += i * A[i];
        }
        int max = prevRotationSum;
        for (int i = A.length -1; i > 0; i--){
            prevRotationSum += sumA - A.length * A[i];
            max = Math.max(prevRotationSum, max);
        }
        return max;
    }
This is essentially a Math problem.
Consider the array [ A, B, C, D ] with very simple coefficients as following:
Consider the array [ A, B, C, D ] with very simple coefficients as following:
f(0) = 0A + 1B + 2C + 3D
f(1) = 3A + 0B + 1C + 2D
f(2) = 2A + 3B + 0C + 1D
f(3) = 1A + 2B + 3C + 0D
f(1) = 3A + 0B + 1C + 2D
f(2) = 2A + 3B + 0C + 1D
f(3) = 1A + 2B + 3C + 0D
We can see from above that:
f(0) -> f(1) -> f(2) -> f(3)
f(i) = f(i - 1) - SUM(A -> B) + N * A[i - 1]
f(0) -> f(1) -> f(2) -> f(3)
f(i) = f(i - 1) - SUM(A -> B) + N * A[i - 1]
    public int maxRotateFunction(int[] A) {
        int n = A.length;
 int sum = 0;
 int candidate = 0;
 for (int i = 0; i < n; i++) {
  sum += A[i];
  candidate += A[i] * i;
 }
 int best = candidate;
 for (int i = 1; i < n; i++) {
  candidate = candidate - sum + A[i - 1] * n;
  best = Math.max(best, candidate);
 }
 return best;
    } public int maxRotateFunction(int[] A) {
  int n = A.length;
  int sum = 0;
  int candidate = 0;
  for (int i = 0; i < n; i++) {
   sum += A[i];
   candidate += A[i] * i;
  }
  int best = candidate;
  for (int i = n - 1; i > 0; i--) {
   candidate = candidate + sum - A[i] * n;
   best = Math.max(best, candidate);
  }
  return best;
 }
假设数组A的长度为5,其旋转函数F的系数向量如下所示:
用每一行系数与其上一行做差,差值恰好为
sum(A) + size * A[size - x],其中x为行数
因此,通过一次遍历即可求出F(0), F(1), ..., F(n-1)的最大值。
    def maxRotateFunction(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        size = len(A)
        sums = sum(A)
        sumn = sum(x * n for x, n in enumerate(A))
        ans = sumn
        for x in range(size - 1, 0, -1):
            sumn += sums - size * A[x]
            ans = max(ans, sumn)
        return ans