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++14
// 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
// 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 |
Python3
# 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#
// 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. |
Javascript
<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:
C++
#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 |
Java
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)); } } |
Python
# 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)) |
C#
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)); } } |
Javascript
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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!