给定数组的所有旋转中 i*arr[i] 的最大总和的Java程序
给定一个包含 n 个整数的数组 arr[],找到使 i*arr[i] 的值之和最大的最大值,其中 i 从 0 变化到 n-1。
例子:
Input: arr[] = {8, 3, 1, 2}
Output: 29
Explanation: Lets look at all the 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*3 = 17
Input: arr[] = {3, 2, 1}
Output: 7
Explanation: Lets look at all the rotations,
{3, 2, 1} = 3*0 + 2*1 + 1*2 = 4
{2, 1, 3} = 2*0 + 1*1 + 3*2 = 7
{1, 3, 2} = 1*0 + 3*1 + 2*2 = 7
方法 1 :该方法讨论了需要 O(n 2 ) 时间的朴素解决方案。
该解决方案涉及在每次旋转中找到数组的所有元素的总和,然后确定最大总和值。
- 方法:一个简单的解决方案是尝试所有可能的旋转。计算每次旋转的 i*arr[i] 总和并返回最大总和。
- 算法:
- 将数组中的所有值从 0 旋转到 n。
- 计算每次旋转的总和。
- 检查最大总和是否大于当前总和,然后更新最大总和。
- 执行:
Java
// A Naive Java program to find
// maximum sum rotation
import java.util.*;
import java.io.*;
class GFG {
// Returns maximum value of i*arr[i]
static int maxSum(int arr[], int n)
{
// Initialize result
int res = Integer.MIN_VALUE;
// 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
// actually 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 = Math.max(res, curr_sum);
}
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 Sahil_Bansall
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
Java
// Java program to find maximum sum
// of all rotation of i*arr[i] using pivot.
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG
{
// function definition
static int maxSum(int arr[], int n)
{
int sum = 0;
int i;
int pivot = findPivot(arr, n);
// difference in pivot and index of
// last element of array
int diff = n - 1 - pivot;
for(i = 0; i < n; i++)
{
sum= sum + ((i + diff) % n) * arr[i];
}
return sum;
}
// function to find pivot
static int findPivot(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
if(arr[i] > arr[(i + 1) % n])
return i;
}
return 0;
}
// Driver code
public static void main(String args[])
{
// rotated input array
int arr[] = {8, 3, 1, 2};
int n = arr.length;
int max = maxSum(arr,n);
System.out.println(max);
}
}
输出 :
29
- 复杂性分析:
- 时间复杂度: O(n 2 )
- 辅助空间: O(1)
方法2 :该方法讨论了在O(n)时间内解决问题的有效解决方案。在朴素的解决方案中,每次旋转都会计算这些值。因此,如果这可以在恒定时间内完成,那么复杂性将会降低。
- 方法:基本方法是从以前的旋转计算新旋转的总和。这带来了一个相似性,其中只有第一个和最后一个元素的乘数发生剧烈变化,并且每个其他元素的乘数增加或减少 1。因此,通过这种方式,可以从当前旋转的总和计算下一个旋转的总和。
- 算法:
这个想法是使用先前旋转的值来计算旋转的值。当一个数组旋转 1 时,i*arr[i] 的总和会发生以下变化。- arr[i-1] 的乘数从 0 变为 n-1,即 arr[i-1] * (n-1) 与当前值相加。
- 其他项的乘数减 1。即,从当前值中减去 (cum_sum – arr[i-1]),其中 cum_sum 是所有数字的总和。
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
- 实施:
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
输出:
29
- 复杂性分析:
- 时间复杂度: O(n)。
因为从 0 到 n 需要一个循环来检查所有旋转,并且当前旋转的总和是从O(1)时间内的先前旋转计算的)。 - 辅助空间: O(1)。
由于不需要额外的空间,因此空间复杂度将为O(1)
- 时间复杂度: O(n)。
方法 3 :该方法讨论了在 O(n) 时间内使用枢轴的解决方案。 pivot 方法只能用于排序或旋转排序数组的情况。例如:{1, 2, 3, 4} 或 {2, 3, 4, 1}, {3, 4, 1, 2} 等。
- 方法:让我们假设一个排序数组的情况。正如我们所知,对于数组,最大和将是当数组按升序排序时。如果是已排序的旋转数组,我们可以旋转数组以使其升序。因此,在这种情况下,需要找到枢轴元素,然后才能计算最大和。
- 算法:
- 找到数组的枢轴:如果 arr[i] > arr[(i+1)%n] 那么它就是枢轴元素。 (i+1)%n 用于检查最后一个和第一个元素。
- 获得枢轴后,可以通过找到与枢轴的差值来计算总和,这将是乘数,并在计算总和时将其与当前元素相乘
- 实现:
Java
// Java program to find maximum sum // of all rotation of i*arr[i] using pivot. import java.util.*; import java.lang.*; import java.io.*; class GFG { // function definition static int maxSum(int arr[], int n) { int sum = 0; int i; int pivot = findPivot(arr, n); // difference in pivot and index of // last element of array int diff = n - 1 - pivot; for(i = 0; i < n; i++) { sum= sum + ((i + diff) % n) * arr[i]; } return sum; } // function to find pivot static int findPivot(int arr[], int n) { int i; for(i = 0; i < n; i++) { if(arr[i] > arr[(i + 1) % n]) return i; } return 0; } // Driver code public static void main(String args[]) { // rotated input array int arr[] = {8, 3, 1, 2}; int n = arr.length; int max = maxSum(arr,n); System.out.println(max); } }
输出:
29
- 复杂性分析:
- 时间复杂度: O(n)
因为只需要一个循环就可以从 0 遍历到 n 来找到枢轴。要找到总和,需要另一个循环,因此复杂度仍然为O(n) 。 - 辅助空间: O(1)。
我们不需要额外的空间,所以辅助空间是O(1)
- 时间复杂度: O(n)
有关详细信息,请参阅有关给定数组的所有旋转中 i*arr[i] 的最大总和的完整文章!
- 复杂性分析: