Given an array arr[] consisting of N integers and a positive integer K, the task is to find the largest sum of any contiguous subarray in the modified array formed by repeating the given array K times.
Examples:
Input: arr[] = {-1, 10, 20}, K = 2
Output: 59
Explanation:
After concatenating the array twice, the array modifies to {-1, 10, 20, -1, 10, 20}.
The subarray with the maximum sum is over the range [1, 5] i.e {10, 20, -1, 10, 20}.Input: arr[] = {10, 20, -30, -1, 40}, K =10
Output: 391
Naive Approach: The simplest approach to solve the problem is discussed in Set-1.
Efficient Approach: The above approach can be optimized further based on the following observations:
- If the sum of the array is greater than 0, then it will contribute to the answer. Otherwise, it is not good to include all array elements into the maximum subarray.
- Suppose variables maxPrefix and maxSufix store the maximum prefix sum and maximum suffix sum of a twice repeated array.
-
Therefore, the maximum sum subarray can be formed by either of the following ways:
- Appending the elements of the maxSufix of the array formed by combining the first two arrays, then appending the remaining N-2 arrays.
- First, appending the N-2 arrays and then appending the elements of the maxPrefix of the array formed by combining the last two arrays.
- Taking all the elements of the maximum sum subarray of a twice repeated array.
Follow the steps below to solve the problem:
- Find the sum of the array arr[] and store it in a variable, say sum1.
- Initialize a variable, say sum and ans as 0 to store the current maximum sum and the answer.
- If K = 1, print the maximum subarray sum of the array arr[].
- Otherwise, insert the elements of the array arr[] from [0, N-1] into the array say V[] twice.
- Find the maximum prefix sum of the array V[] and store it in a variable, say maxPrefix.
- Find the maximum suffix sum of the array V[] and store it in a variable, say maxSufix.
-
Iterate in the range [0, 2*N-1] using the variable i and perform the following steps:
- Modify the value of sum as max(sum + arr[i], arr[i]) and update the value of ans as max(ans, sum).
- If sum1 > 0, then update ans to the maximum of {ans, sum1*(K-2)+maxPrefix, sum1*(K-2)+maxSufix}.
- Finally, after completing the above steps, print the value of ans as the answer.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to find contiguous subarray with // maximum sum if array is repeated K times int maxSubArraySumRepeated( int arr[], int N, int K)
{ // Store the sum of the array arr[]
int sum = 0;
// Traverse the array and find sum
for ( int i = 0; i < N; i++)
sum += arr[i];
int curr = arr[0];
// Store the answer
int ans = arr[0];
// If K = 1
if (K == 1) {
// Apply Kadane algorithm to find sum
for ( int i = 1; i < N; i++) {
curr = max(arr[i], curr + arr[i]);
ans = max(ans, curr);
}
// Return the answer
return ans;
}
// Stores the twice repeated array
vector< int > V;
// Traverse the range [0, 2*N]
for ( int i = 0; i < 2 * N; i++) {
V.push_back(arr[i % N]);
}
// Stores the maximum suffix sum
int maxSuf = V[0];
// Stores the maximum prefix sum
int maxPref = V[2 * N - 1];
curr = V[0];
for ( int i = 1; i < 2 * N; i++) {
curr += V[i];
maxPref = max(maxPref, curr);
}
curr = V[2 * N - 1];
for ( int i = 2 * N - 2; i >= 0; i--) {
curr += V[i];
maxSuf = max(maxSuf, curr);
}
curr = V[0];
// Apply Kadane algorithm for 2 repetition
// of the array
for ( int i = 1; i < 2 * N; i++) {
curr = max(V[i], curr + V[i]);
ans = max(ans, curr);
}
// If the sum of the array is greater than 0
if (sum > 0) {
int temp = 1LL * sum * (K - 2);
ans = max(ans, max(temp + maxPref, temp + maxSuf));
}
// Return the answer
return ans;
} // Driver Code int main()
{ // Given Input
int arr[] = { 10, 20, -30, -1, 40 };
int N = sizeof (arr) / sizeof (arr[0]);
int K = 10;
// Function Call
cout << maxSubArraySumRepeated(arr, N, K);
return 0;
} |
// Java program for the above approach import java.util.*;
class GFG{
// Function to find contiguous subarray with // maximum sum if array is repeated K times static int maxSubArraySumRepeated( int [] arr, int N,
int K)
{ // Store the sum of the array arr[]
int sum = 0 ;
// Traverse the array and find sum
for ( int i = 0 ; i < N; i++)
sum += arr[i];
int curr = arr[ 0 ];
// Store the answer
int ans = arr[ 0 ];
// If K = 1
if (K == 1 )
{
// Apply Kadane algorithm to find sum
for ( int i = 1 ; i < N; i++)
{
curr = Math.max(arr[i], curr + arr[i]);
ans = Math.max(ans, curr);
}
// Return the answer
return ans;
}
// Stores the twice repeated array
ArrayList<Integer> V = new ArrayList<Integer>();
// Traverse the range [0, 2*N]
for ( int i = 0 ; i < 2 * N; i++)
{
V.add(arr[i % N]);
}
// Stores the maximum suffix sum
int maxSuf = V.get( 0 );
// Stores the maximum prefix sum
int maxPref = V.get( 2 * N - 1 );
curr = V.get( 0 );
for ( int i = 1 ; i < 2 * N; i++)
{
curr += V.get(i);
maxPref = Math.max(maxPref, curr);
}
curr = V.get( 2 * N - 1 );
for ( int i = 2 * N - 2 ; i >= 0 ; i--)
{
curr += V.get(i);
maxSuf = Math.max(maxSuf, curr);
}
curr = V.get( 0 );
// Apply Kadane algorithm for 2 repetition
// of the array
for ( int i = 1 ; i < 2 * N; i++)
{
curr = Math.max(V.get(i), curr + V.get(i));
ans = Math.max(ans, curr);
}
// If the sum of the array is greater than 0
if (sum > 0 )
{
int temp = sum * (K - 2 );
ans = Math.max(ans, Math.max(temp + maxPref,
temp + maxSuf));
}
// Return the answer
return ans;
} // Driver Code public static void main(String args[])
{ // Given Input
int []arr = { 10 , 20 , - 30 , - 1 , 40 };
int N = arr.length;
int K = 10 ;
// Function Call
System.out.print(maxSubArraySumRepeated(arr, N, K));
} } // This code is contributed by SURENDRA_GANGWAR |
# python 3 program for the above approach # Function to find contiguous subarray with # maximum sum if array is repeated K times def maxSubArraySumRepeated(arr, N, K):
# Store the sum of the array arr[]
sum = 0
# Traverse the array and find sum
for i in range (N):
sum + = arr[i]
curr = arr[ 0 ]
# Store the answer
ans = arr[ 0 ]
# If K = 1
if (K = = 1 ):
# Apply Kadane algorithm to find sum
for i in range ( 1 ,N, 1 ):
curr = max (arr[i], curr + arr[i])
ans = max (ans, curr)
# Return the answer
return ans
# Stores the twice repeated array
V = []
# Traverse the range [0, 2*N]
for i in range ( 2 * N):
V.append(arr[i % N])
# Stores the maximum suffix sum
maxSuf = V[ 0 ]
# Stores the maximum prefix sum
maxPref = V[ 2 * N - 1 ]
curr = V[ 0 ]
for i in range ( 1 , 2 * N, 1 ):
curr + = V[i]
maxPref = max (maxPref, curr)
curr = V[ 2 * N - 1 ]
i = 2 * N - 2
while (i > = 0 ):
curr + = V[i]
maxSuf = max (maxSuf, curr)
i - = 1
curr = V[ 0 ]
# Apply Kadane algorithm for 2 repetition
# of the array
for i in range ( 1 , 2 * N, 1 ):
curr = max (V[i], curr + V[i])
ans = max (ans, curr)
# If the sum of the array is greater than 0
if ( sum > 0 ):
temp = sum * (K - 2 )
ans = max (ans, max (temp + maxPref, temp + maxSuf))
# Return the answer
return ans
# Driver Code if __name__ = = '__main__' :
# Given Input
arr = [ 10 , 20 , - 30 , - 1 , 40 ]
N = len (arr)
K = 10
# Function Call
print (maxSubArraySumRepeated(arr, N, K))
# This code is contributed by ipg2016107.
|
// C# program for the above approach using System;
using System.Collections.Generic;
class GFG {
// Function to find contiguous subarray with
// maximum sum if array is repeated K times
static int maxSubArraySumRepeated( int [] arr, int N,
int K)
{
// Store the sum of the array arr[]
int sum = 0;
// Traverse the array and find sum
for ( int i = 0; i < N; i++)
sum += arr[i];
int curr = arr[0];
// Store the answer
int ans = arr[0];
// If K = 1
if (K == 1) {
// Apply Kadane algorithm to find sum
for ( int i = 1; i < N; i++) {
curr = Math.Max(arr[i], curr + arr[i]);
ans = Math.Max(ans, curr);
}
// Return the answer
return ans;
}
// Stores the twice repeated array
List< int > V = new List< int >();
// Traverse the range [0, 2*N]
for ( int i = 0; i < 2 * N; i++) {
V.Add(arr[i % N]);
}
// Stores the maximum suffix sum
int maxSuf = V[0];
// Stores the maximum prefix sum
int maxPref = V[2 * N - 1];
curr = V[0];
for ( int i = 1; i < 2 * N; i++) {
curr += V[i];
maxPref = Math.Max(maxPref, curr);
}
curr = V[2 * N - 1];
for ( int i = 2 * N - 2; i >= 0; i--) {
curr += V[i];
maxSuf = Math.Max(maxSuf, curr);
}
curr = V[0];
// Apply Kadane algorithm for 2 repetition
// of the array
for ( int i = 1; i < 2 * N; i++) {
curr = Math.Max(V[i], curr + V[i]);
ans = Math.Max(ans, curr);
}
// If the sum of the array is greater than 0
if (sum > 0) {
int temp = sum * (K - 2);
ans = Math.Max(ans, Math.Max(temp + maxPref,
temp + maxSuf));
}
// Return the answer
return ans;
}
// Driver Code
public static void Main()
{
// Given Input
int [] arr = { 10, 20, -30, -1, 40 };
int N = arr.Length;
int K = 10;
// Function Call
Console.WriteLine(
maxSubArraySumRepeated(arr, N, K));
}
} // This code is contributed by ukasp. |
<script> // JavaScript program for the above approach // Function to find contiguous subarray with // maximum sum if array is repeated K times function maxSubArraySumRepeated(arr, N, K) {
// Store the sum of the array arr[]
let sum = 0;
// Traverse the array and find sum
for (let i = 0; i < N; i++)
sum += arr[i];
let curr = arr[0];
// Store the answer
let ans = arr[0];
// If K = 1
if (K == 1) {
// Apply Kadane algorithm to find sum
for (let i = 1; i < N; i++) {
curr = Math.max(arr[i], curr + arr[i]);
ans = Math.max(ans, curr);
}
// Return the answer
return ans;
}
// Stores the twice repeated array
let V = [];
// Traverse the range [0, 2*N]
for (let i = 0; i < 2 * N; i++) {
V.push(arr[i % N]);
}
// Stores the maximum suffix sum
let maxSuf = V[0];
// Stores the maximum prefix sum
let maxPref = V[2 * N - 1];
curr = V[0];
for (let i = 1; i < 2 * N; i++) {
curr += V[i];
maxPref = Math.max(maxPref, curr);
}
curr = V[2 * N - 1];
for (let i = 2 * N - 2; i >= 0; i--) {
curr += V[i];
maxSuf = Math.max(maxSuf, curr);
}
curr = V[0];
// Apply Kadane algorithm for 2 repetition
// of the array
for (let i = 1; i < 2 * N; i++) {
curr = Math.max(V[i], curr + V[i]);
ans = Math.max(ans, curr);
}
// If the sum of the array is greater than 0
if (sum > 0) {
let temp = sum * (K - 2);
ans = Math.max(ans, Math.max(temp + maxPref, temp + maxSuf));
}
// Return the answer
return ans;
} // Driver Code // Given Input let arr = [10, 20, -30, -1, 40]; let N = arr.length; let K = 10; // Function Call document.write(maxSubArraySumRepeated(arr, N, K)); </script> |
391
Time Complexity: O(N)
Auxiliary Space: O(N)
Another Approach:
- If K==1, use kadane algorithm to find the maximum subarray sum
-
Else find the sum of the whole array
- If sum<0, it means after concatenating K more arrays, it will also result in negative value of sum. So, use kadane algorithm after concatenating one more array, which return the sum of maximum suffix from first array and maximum prefix of the second array.
- Else if sum>=0, then we get the maximum subarray sum from maximum of prefix from the last array and maximum of suffix from the first array and the sum of (k-2) arrays i.e. maximum suffix sum(from the first array) + sum*(k-2) + maximum prefix sum(from the last array);
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
//function to find the maximum subarray sum //kadane algorithm int kadane( int arr[], int N){
int currsum=0;
int maxsum=INT_MIN;
for ( int i=0;i<N;i++){
currsum+=arr[i];
if (currsum<0){
currsum=0;
}
maxsum=max(maxsum, currsum);
}
return maxsum;
} //after concatenating two arrays, //apply kadane to it int twiceKadane( int arr[], int N){
int currsum=0, maxsum=INT_MIN;
for ( int i=0;i<2*N;i++){
currsum+= arr[i%N];
if (currsum<0){
currsum=0;
}
maxsum=max(maxsum, currsum);
}
return maxsum;
} int maxSubArraySumRepeated( int arr[], int N, int K){
//if k==1, normally return kadane
if (K==1){
return kadane(arr, N);
}
long long sum=0;
//find the sum of the whole array
for ( int i=0;i<N;i++){
sum+=arr[i];
}
//if sum is negative of the array, then after concatenating the k
//arrays, it will also gives negative sum
//So, the repetitions of 2 arrays will give the result
if (sum<0){
return twiceKadane(arr, N);
}
//if sum>0 or sum=0, then the repetition of the 2 arrays and the
//sum of k-2 arrays will give the result
else {
return twiceKadane(arr, N) + sum*(K-2);
}
} // Driver Code int main()
{ // Given Input
int arr[] = { 10, 20, -30, -1, 40 };
int N = sizeof (arr) / sizeof (arr[0]);
int K = 10;
// Function Call
cout << maxSubArraySumRepeated(arr, N, K);
return 0;
} //this code is contributed by 525tamannacse1 |
import java.util.Arrays;
public class GFG {
// Function to find the maximum subarray sum (Kadane's Algorithm)
static int kadane( int [] arr, int N) {
int currSum = 0 ;
int maxSum = Integer.MIN_VALUE;
for ( int i = 0 ; i < N; i++) {
currSum += arr[i];
if (currSum < 0 ) {
currSum = 0 ;
}
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
}
// After concatenating two arrays, apply Kadane's Algorithm to it
static int twiceKadane( int [] arr, int N) {
int currSum = 0 ;
int maxSum = Integer.MIN_VALUE;
for ( int i = 0 ; i < 2 * N; i++) {
currSum += arr[i % N];
if (currSum < 0 ) {
currSum = 0 ;
}
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
}
static int maxSubArraySumRepeated( int [] arr, int N, int K) {
// If K==1, normally return Kadane's result
if (K == 1 ) {
return kadane(arr, N);
}
long sum = 0 ;
// Find the sum of the whole array
for ( int i = 0 ; i < N; i++) {
sum += arr[i];
}
// If sum is negative of the array, then after concatenating the K arrays,
// it will also give a negative sum, so the repetitions of 2 arrays will give the result
if (sum < 0 ) {
return twiceKadane(arr, N);
}
// If sum > 0 or sum = 0, then the repetition of the 2 arrays and the
// sum of (K-2) arrays will give the result
else {
return twiceKadane(arr, N) + ( int ) (sum * (K - 2 ));
}
}
// Driver Code
public static void main(String[] args) {
// Given Input
int [] arr = { 10 , 20 , - 30 , - 1 , 40 };
int N = arr.length;
int K = 10 ;
// Function Call
System.out.println(maxSubArraySumRepeated(arr, N, K));
}
} |
# Function to find the maximum subarray sum (Kadane's Algorithm) def kadane(arr, N):
currSum = 0
maxSum = float ( '-inf' )
for i in range (N):
currSum + = arr[i]
if currSum < 0 :
currSum = 0
maxSum = max (maxSum, currSum)
return maxSum
# After concatenating two arrays, apply Kadane's Algorithm to it def twiceKadane(arr, N):
currSum = 0
maxSum = float ( '-inf' )
for i in range ( 2 * N):
currSum + = arr[i % N]
if currSum < 0 :
currSum = 0
maxSum = max (maxSum, currSum)
return maxSum
def maxSubArraySumRepeated(arr, N, K):
# If K == 1, return Kadane's result
if K = = 1 :
return kadane(arr, N)
sum_val = sum (arr)
# If the sum is negative, repetitions of 2 arrays will give the result
if sum_val < 0 :
return twiceKadane(arr, N)
# If sum >= 0, repetitions of 2 arrays and the sum of (K-2) arrays will give the result
else :
return twiceKadane(arr, N) + int (sum_val * (K - 2 ))
# Given Input arr = [ 10 , 20 , - 30 , - 1 , 40 ]
N = len (arr)
K = 10
# Function Call print (maxSubArraySumRepeated(arr, N, K))
|
using System;
class Program {
// Function to find the maximum subarray sum using
// Kadane's algorithm
static int Kadane( int [] arr, int N)
{
int currSum = 0;
int maxSum = int .MinValue;
for ( int i = 0; i < N; i++) {
currSum += arr[i];
if (currSum < 0) {
currSum = 0;
}
maxSum = Math.Max(maxSum, currSum);
}
return maxSum;
}
// Function to find the maximum subarray sum after
// repeating the array K times
static int MaxSubArraySumRepeated( int [] arr, int N,
int K)
{
// If K is 1, return the result of a single
// repetition using Kadane's algorithm
if (K == 1) {
return Kadane(arr, N);
}
long sum = 0;
// Find the sum of the whole array
for ( int i = 0; i < N; i++) {
sum += arr[i];
}
// If the sum is less than 0, then the result will
// be from repeated 2 arrays
if (sum < 0) {
return TwiceKadane(arr, N);
}
// If the sum is greater than or equal to 0, then
// the result will be from repeated 2 arrays and the
// sum of (K-2) arrays
else {
return TwiceKadane(arr, N)
+ ( int )(sum * (K - 2));
}
}
// Function to find the maximum subarray sum after
// repeating the array twice
static int TwiceKadane( int [] arr, int N)
{
int currSum = 0;
int maxSum = int .MinValue;
for ( int i = 0; i < 2 * N; i++) {
currSum += arr[i % N];
if (currSum < 0) {
currSum = 0;
}
maxSum = Math.Max(maxSum, currSum);
}
return maxSum;
}
static void Main()
{
// Given Input
int [] arr = { 10, 20, -30, -1, 40 };
int N = arr.Length;
int K = 10;
// Function Call
Console.WriteLine(
MaxSubArraySumRepeated(arr, N, K));
}
} |
function kadane(arr, N) {
let currSum = 0;
let maxSum = Number.NEGATIVE_INFINITY;
for (let i = 0; i < N; i++) {
currSum += arr[i];
if (currSum < 0) {
currSum = 0;
}
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
} // After concatenating two arrays // apply Kadane's Algorithm to it function twiceKadane(arr, N) {
let currSum = 0;
let maxSum = Number.NEGATIVE_INFINITY;
for (let i = 0; i < 2 * N; i++) {
currSum += arr[i % N];
if (currSum < 0) {
currSum = 0;
}
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
} function GFG(arr, N, K) {
// If K==1, normally return Kadane's result
if (K === 1) {
return kadane(arr, N);
}
let sum = 0;
// Find the sum of the whole array
for (let i = 0; i < N; i++) {
sum += arr[i];
}
if (sum < 0) {
return twiceKadane(arr, N);
}
// If sum > 0 or sum = 0, then the repetition of the 2 arrays and
// sum of (K-2) arrays will give the result
else {
return twiceKadane(arr, N) + (sum * (K - 2));
}
} // Given Input const arr = [10, 20, -30, -1, 40]; const N = arr.length; const K = 10; // Function Call console.log(GFG(arr, N, K)); |
391
Time Complexity: O(N) + O(N) + O(2*N), time complexity of kadane() and maxSubArraySumRepeated() is O(N) as they traverse from 0 to N-1 and the time complexity of twiceKadance() is O(2*N) as it traverse from 0 to 2*N-1.
Space Complexity: O(1)