Maximum sum of i*arr[i] among all rotations of a given array

3.1

Given an array arr[] of n integers, find the maximum that maximizes sum of value of i*arr[i] where i varies from 0 to n-1.

Examples:

Input : arr[] = {8, 3, 1, 2}
Output : 29
Explanation : Let us see all rotations
{8, 3, 1, 2} = 8*0 + 3*1 + 1*2 + 2*3 = 11
{3, 1, 2, 8} = 3*0 + 1*1 + 2*2 + 8*3 = 29
{1, 2, 8, 3} = 1*0 + 2*1 + 8*2 + 3*3 = 27
{2, 8, 3, 1} = 2*0 + 8*1 + 3*2 + 1*1 = 17

Input : arr[] = {3, 2, 1}
Output : 8

Method 1 (Naive Solution : O(n2) )

A simple solution is to try all possible rotations. Compute sum of i*arr[i] for every rotation and return maximum sum. Below is C++ implementation of this idea.

// A Naive C++ program to find maximum sum rotation
#include<bits/stdc++.h>
using namespace std;

// Returns maximum value of i*arr[i]
int maxSum(int arr[], int n)
{
   // Initialize result
   int res = INT_MIN;

   // Consider rotation beginning with i
   // for all possible values of i.
   for (int i=0; i<n; i++)
   {

     // Initialize sum of current rotation
     int curr_sum = 0;

     // Compute sum of all values. We don't
     // acutally rotation the array, but compute
     // sum by finding ndexes when arr[i] is
     // first element
     for (int j=0; j<n; j++)
     {
         int index = (i+j)%n;
         curr_sum += j*arr[index];
     }

     // Update result if required
     res = max(res, curr_sum);
   }

   return res;
}

// Driver code
int main()
{
    int arr[] = {8, 3, 1, 2};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << maxSum(arr, n) << endl;
    return 0;
}

Output:

29

Time Complexity : O(n2)
Auxiliary Space : O(1)

Method 2 (Efficient Solution : O(n) )

The idea is to compute value of a rotation using value of previous rotation. When we rotate an array by one, following changes happen in sum of i*arr[i].
1) Multiplier of arr[i-1] changes from 0 to n-1, i.e., arr[i-1] * (n-1) is added to current value.
2) Multipliers of other terms is decremented by 1. i.e., (cum_sum – arr[i-1]) is subtracted from current value where cum_sum is sum of all numbers.

next_val = curr_val - (cum_sum - arr[i-1]) + arr[i-1] * (n-1);

next_val = Value of ∑i*arr[i] after one rotation.
curr_val = Current value of ∑i*arr[i] 
cum_sum = Sum of all array elements, i.e., ∑arr[i].

Lets take example {1, 2, 3}. Current value is 1*0+2*1+3*2
= 8. Shifting it by one will make it {2, 3, 1} and next value
will be 8 - (6 - 1) + 1*2 = 5 which is same as 2*0 + 3*1 + 1*2

Below is the implementation of this idea.

C++

// An efficient C++ program to compute
// maximum sum of i*arr[i]
#include<bits/stdc++.h>
using namespace std;

int maxSum(int arr[], int n)
{
    // Compute sum of all array elements
    int cum_sum = 0;
    for (int i=0; i<n; i++)
        cum_sum += arr[i];

    // Compute sum of i*arr[i] for initial
    // configuration.
    int curr_val = 0;
    for (int i=0; i<n; i++)
        curr_val += i*arr[i];

    // Initialize result
    int res = curr_val;

    // Compute values for other iterations
    for (int i=1; i<n; i++)
    {
        // Compute next value using previous value in
        // O(1) time
        int next_val = curr_val - (cum_sum - arr[i-1])
                       + arr[i-1] * (n-1);

        // Update current value
        curr_val = next_val;

        // Update result if required
        res = max(res, next_val);
    }

    return res;
}

// Driver code
int main()
{
    int arr[] = {8, 3, 1, 2};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << maxSum(arr, n) << endl;
    return 0;
}

Java

// An efficient Java program to compute
// maximum sum of i*arr[i]
import java.io.*;

class GFG {
    
    static int maxSum(int arr[], int n)
    {
        // Compute sum of all array elements
        int cum_sum = 0;
        for (int i = 0; i < n; i++)
            cum_sum += arr[i];

        // Compute sum of i*arr[i] for 
        // initial configuration.
        int curr_val = 0;
        for (int i = 0; i < n; i++)
            curr_val += i * arr[i];

        // Initialize result
        int res = curr_val;

        // Compute values for other iterations
        for (int i = 1; i < n; i++)
        {
            // Compute next value using previous
            // value in O(1) time
            int next_val = curr_val - (cum_sum -
                          arr[i-1]) + arr[i-1] *
                          (n-1);

            // Update current value
            curr_val = next_val;

            // Update result if required
            res = Math.max(res, next_val);
        }

        return res;
    }

    // Driver code
    public static void main(String[] args)
    {
        int arr[] = {8, 3, 1, 2};
        int n = arr.length;
        System.out.println(maxSum(arr, n));
    }
}
// This code is contributed by Prerna Saini


Output:

29

Time Complexity : O(n)
Auxiliary Space : O(1)

This article is contributed by Shubham Joshi. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.

Recommended Posts:



3.1 Average Difficulty : 3.1/5.0
Based on 75 vote(s)










Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.