Open In App

Maximum subarray sum in an array created after repeated concatenation | Set-2

Last Updated : 16 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  1. 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.
  2. Suppose variables maxPrefix and maxSufix store the maximum prefix sum and maximum suffix sum of a twice repeated array.
  3. Therefore, the maximum sum subarray can be formed by either of the following ways:
    1. Appending the elements of the maxSufix of the array formed by combining the first two arrays, then appending the remaining N-2 arrays.
    2. First, appending the N-2 arrays and then appending the elements of the maxPrefix of the array formed by combining the last two arrays.
    3. Taking all the elements of the maximum sum subarray of a twice repeated array.

Follow the steps below to solve the problem:

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>


Output

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));


Output

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)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads