Open In App

Largest Sum Contiguous Subarray having unique elements

Given an array arr[] of N positive integers, the task is to find the subarray having maximum sum among all subarrays having unique elements and print its sum. 

Input arr[] = {1, 2, 3, 3, 4, 5, 2, 1}
Output: 15
Explanation:
The subarray having maximum sum with distinct element is {3, 4, 5, 2, 1}.
Therefore, sum is = 3 + 4 + 5 + 2 + 1 = 15

Input: arr[] = {1, 2, 3, 1, 5}
Output: 11
Explanation:
The subarray having maximum sum with distinct element is {2, 3, 1, 5}.
Therefore, sum is = 2 + 3 + 1 + 5 = 11.

Naive Approach: The simplest approach to solve the problem is to generate all possible subarrays and for each subarray, check if all its elements are unique or not. Find the maximum sum among such subarrays and print it.




// C++ program for
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate required
// maximum subarray sum
int maxSumSubarray(int arr[], int n)
{
    int result = 0;
 
    for (int i = 0; i < n; i++) {
        int sum = 0;
 
        // For keep track of duplicate elements in current
        // subarray
        unordered_map<int, int> unmap;
         
        for (int j = i; j < n; j++) {
            unmap[arr[j]]++;
            sum += arr[j];
 
            // Check if current subarray contains any
            // duplicate
            if (unmap.size() == (j - i + 1)) {
                result = max(result, sum);
            }
            else {
                break;
            }
        }
    }
    return result;
}
 
// Driver Code
int main()
{
    // Given array arr[]
    int arr[] = { 1, 2, 3, 3, 4, 5, 2, 1 };
 
    // Function Call
    int ans = maxSumSubarray(arr, 8);
 
    // Print the maximum sum
    cout << (ans);
}




/*package whatever //do not write package name here */
 
import java.io.*;
import java.util.*;
 
class GFG
{
  // Function to calculate required
  // maximum subarray sum
  public static int maxSumSubarray(int arr[], int n)
  {
    int result = 0;
 
    for (int i = 0; i < n; i++) {
      int sum = 0;
 
      // For keep track of duplicate elements in current
      // subarray
      HashMap<Integer,Integer> hm=new HashMap<>();
 
      for (int j = i; j < n; j++) {
        hm.put(arr[j],hm.getOrDefault(arr[j],0)+1);
        sum += arr[j];
 
        // Check if current subarray contains any
        // duplicate
        if (hm.size() == (j - i + 1)) {
          result = Math.max(result, sum);
        }
        else {
          break;
        }
      }
    }
    return result;
  }
 
  public static void main (String[] args)
  {
     
    // Given array arr[]
    int arr[] = { 1, 2, 3, 3, 4, 5, 2, 1 };
 
    // Function Call
    int ans = maxSumSubarray(arr, 8);
 
    // Print the maximum sum
    System.out.println(ans);
  }
}
 
// This code is contributed by sourabhdalal0001.




from collections import defaultdict
 
  #Function to calculate required
  #maximum subarray sum
def maxSumSubarray(arr, n):
    result = 0
    for i in range(n):
        sum = 0
        unmap = defaultdict(int)
        for j in range(i, n):
            unmap[arr[j]] += 1
            sum += arr[j]
            if len(unmap) == (j - i + 1):
                result = max(result, sum)
            else:
                break
    return result
 
 
# Given array arr[]
arr = [1, 2, 3, 3, 4, 5, 2, 1]
 
# Function Call
ans = maxSumSubarray(arr, 8)
 
# Print the maximum sum
print(ans)




using System;
using System.Collections.Generic;
 
class GFG {
    // Function to calculate required
    // maximum subarray sum
    public static int maxSumSubarray(int[] arr, int n)
    {
        int result = 0;
 
        for (int i = 0; i < n; i++) {
            int sum = 0;
 
            // For keep track of duplicate elements in
            // current subarray
            Dictionary<int, int> hm
                = new Dictionary<int, int>();
 
            for (int j = i; j < n; j++) {
                if (hm.ContainsKey(arr[j])) {
                    hm[arr[j]]++;
                }
                else {
                    hm[arr[j]] = 1;
                }
 
                sum += arr[j];
 
                // Check if current subarray contains any
                // duplicate
                if (hm.Count == (j - i + 1)) {
                    result = Math.Max(result, sum);
                }
                else {
                    break;
                }
            }
        }
        return result;
    }
 
    public static void Main(string[] args)
    {
        // Given array arr[]
        int[] arr = { 1, 2, 3, 3, 4, 5, 2, 1 };
 
        // Function Call
        int ans = maxSumSubarray(arr, 8);
 
        // Print the maximum sum
        Console.WriteLine(ans);
    }
}




// Javascript program for the above approach
 
// Function to calculate required
// maximum subarray sum
function maxSumSubarray( arr,  n)
{
    let result = 0;
 
    for (let i = 0; i < n; i++) {
        let sum = 0;
 
        // For keep track of duplicate elements in current
        // subarray
        //unordered_map<int, int> unmap;
        unmap=new Map();
         
        for (let j = i; j < n; j++) {
            if(unmap.has(arr[j]))
                unmap.set(arr[j], unmap.get(arr[j])+1);
            else
                unmap.set(arr[j],1);
            sum += arr[j];
 
            // Check if current subarray contains any
            // duplicate
            if (unmap.size == (j - i + 1)) {
                result = Math.max(result, sum);
            }
            else {
                break;
            }
        }
    }
    return result;
}
 
// Driver Code
// Given array arr[]
let arr = [ 1, 2, 3, 3, 4, 5, 2, 1 ];
 
// Function Call
let ans = maxSumSubarray(arr, 8);
 
// Print the maximum sum
console.log(ans);

Output
15

Time Complexity: O(N2)
Auxiliary Space: O(N) 

Efficient Approach 1: Using Two Pointer Technique 

To optimize the above approach the idea is to use the Two Pointer technique. Follow the steps below to solve the approach: 

  1. Initialize two pointers i and j as 0 and 1 respectively to store the starting and ending index of the resultant subarray.
  2. Initialize a HashSet to store the array elements.
  3. Start from an empty subarray with i = 0 and j = 0 and traverse the array until any duplicate element is found and update the current sum to the maximum sum(say max_sum) if it is found to be greater than the current max_sum.
  4. If the duplicate element is found, increment j and update the variables until only unique elements are left in the current subarray from index j to i.
  5. Repeat the above steps for the rest of the array and keep updating the max_sum.
  6. Print the maximum sum obtained after completing the above steps.

Below is the implementation of the above approach: 




// C++ program for
// the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to calculate required
// maximum subarray sum
int maxSumSubarray(int arr[], int n)
{
  // Initialize two pointers
  int i = 0, j = 1;
  // Stores the unique elements
  set<int> set;
 
  // Insert the first element
  set.insert(arr[0]);
 
  // Current max sum
  int sum = arr[0];
 
  // Global maximum sum
  int maxsum = sum;
 
  while (i < n - 1 && j < n)
  {
    // Update sum & increment j
    // auto pos = s.find(3);
    const bool is_in = set.find(arr[j]) !=
                       set.end();
    if (!is_in)
    {
      sum = sum + arr[j];
      maxsum = max(sum, maxsum);
 
      // Add the current element
      set.insert(arr[j++]);
    }
 
    // Update sum and increment i
    // and remove arr[i] from set
    else
    {
      sum -= arr[i];
 
      // Remove the element
      // from start position
      set.erase(arr[i++]);
    }
  }
 
  // Return the maximum sum
  return maxsum;
}
 
// Driver Code
int  main()
{
  // Given array arr[]
  int arr[] = {1, 2, 3, 1, 5};
 
  // Function Call
  int ans = maxSumSubarray(arr, 5);
 
  // Print the maximum sum
  cout << (ans);
}
 
// This code is contributed by gauravrajput1




// Java program for the above approach
 
import java.io.*;
import java.lang.Math;
import java.util.*;
public class GFG {
 
    // Function to calculate required
    // maximum subarray sum
    public static int
    maxSumSubarray(int[] arr)
    {
 
        // Initialize two pointers
        int i = 0, j = 1;
 
        // Stores the unique elements
        HashSet<Integer> set
            = new HashSet<Integer>();
 
        // Insert the first element
        set.add(arr[0]);
 
        // Current max sum
        int sum = arr[0];
 
        // Global maximum sum
        int maxsum = sum;
 
        while (i < arr.length - 1
               && j < arr.length) {
 
            // Update sum & increment j
            if (!set.contains(arr[j])) {
 
                sum = sum + arr[j];
                maxsum = Math.max(sum,
                                  maxsum);
 
                // Add the current element
                set.add(arr[j++]);
            }
 
            // Update sum and increment i
            // and remove arr[i] from set
            else {
 
                sum -= arr[i];
 
                // Remove the element
                // from start position
                set.remove(arr[i++]);
            }
        }
 
        // Return the maximum sum
        return maxsum;
    }
 
    // Driver Code
    public static void
        main(String[] args)
    {
        // Given array arr[]
        int arr[] = new int[] { 1, 2, 3, 1, 5 };
 
        // Function Call
        int ans = maxSumSubarray(arr);
 
        // Print the maximum sum
        System.out.println(ans);
    }
}




# Python3 program for the above approach
 
# Function to calculate required
# maximum subarray sum
def maxSumSubarray(arr):
 
    # Initialize two pointers
    i = 0
    j = 1
 
    # Stores the unique elements
    set = {}
 
    # Insert the first element
    set[arr[0]] = 1
 
    # Current max sum
    sum = arr[0]
 
    # Global maximum sum
    maxsum = sum
 
    while (i < len(arr) - 1 and
           j < len(arr)):
 
        # Update sum & increment j
        if arr[j] not in set:
            sum = sum + arr[j]
            maxsum = max(sum, maxsum)
 
            # Add the current element
            set[arr[j]] = 1
            j += 1
 
        # Update sum and increment i
        # and remove arr[i] from set
        else:
            sum -= arr[i]
 
            # Remove the element
            # from start position
            del set[arr[i]]
            i += 1
 
    # Return the maximum sum
    return maxsum
 
# Driver Code
if __name__ == '__main__':
 
    # Given array arr[]
    arr = [ 1, 2, 3, 1, 5 ]
 
    # Function call
    ans = maxSumSubarray(arr)
 
    # Print the maximum sum
    print(ans)
 
# This code is contributed by mohit kumar 29




// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
 
  // Function to calculate
  // required maximum subarray sum
  public static int maxSumSubarray(int[] arr)
  {
    // Initialize two pointers
    int i = 0, j = 1;
 
    // Stores the unique elements
    HashSet<int> set =
            new HashSet<int>();
 
    // Insert the first element
    set.Add(arr[0]);
 
    // Current max sum
    int sum = arr[0];
 
    // Global maximum sum
    int maxsum = sum;
 
    while (i < arr.Length - 1 &&
           j < arr.Length)
    {
      // Update sum & increment j
      if (!set.Contains(arr[j]))
      {
        sum = sum + arr[j];
        maxsum = Math.Max(sum,
                          maxsum);
 
        // Add the current element
        set.Add(arr[j++]);
      }
 
      // Update sum and increment i
      // and remove arr[i] from set
      else
      {
        sum -= arr[i];
 
        // Remove the element
        // from start position
        set.Remove(arr[i++]);
      }
    }
 
    // Return the maximum sum
    return maxsum;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    // Given array []arr
    int []arr = new int[] {1, 2,
                           3, 1, 5};
 
    // Function Call
    int ans = maxSumSubarray(arr);
 
    // Print the maximum sum
    Console.WriteLine(ans);
  }
}
 
// This code is contributed by shikhasingrajput




<script>
 
// Javascript program for
// the above approach
 
// Function to calculate required
// maximum subarray sum
function maxSumSubarray(arr, n)
{
     
    // Initialize two pointers
    var i = 0, j = 1;
     
    // Stores the unique elements
    var set = new Set();
     
    // Insert the first element
    set.add(arr[0]);
     
    // Current max sum
    var sum = arr[0];
     
    // Global maximum sum
    var maxsum = sum;
     
    while (i < n - 1 && j < n)
    {
         
        // Update sum & increment j
        // auto pos = s.find(3);
        var is_in = set.has(arr[j]);
        if (!is_in)
        {
            sum = sum + arr[j];
            maxsum = Math.max(sum, maxsum);
             
            // Add the current element
            set.add(arr[j++]);
        }
         
        // Update sum and increment i
        // and remove arr[i] from set
        else
        {
            sum -= arr[i];
             
            // Remove the element
            // from start position
            set.delete(arr[i++]);
        }
    }
     
    // Return the maximum sum
    return maxsum;
}
 
// Driver Code
 
// Given array arr[]
var arr = [ 1, 2, 3, 1, 5 ];
 
// Function Call
var ans = maxSumSubarray(arr, 5);
 
// Print the maximum sum
document.write(ans);
 
// This code is contributed by rutvik_56
 
</script>

Output
11

Time Complexity: O(N)
Auxiliary Space: O(N)

Efficient Approach 2: Using Prefix Sum

To optimize the above approach the idea is to use the Prefix Sum array. Follow the steps below to solve the approach: 

  1. Create an array containing the sum of all elements before index i. This is called the prefix sum array.
  2. Create an hashset containing the index of last occurrence of an element.
  3. Initialize the resultant global maximum sum with 0.
  4. Initialize two pointers i and j at index 0 and traverse the array with the pointer i.
  5. If the current element has occurred before, reinitialize j with the maximum value between j and the last occurrence of the current element.
  6. The resultant global maximum sum = max(global maximum sum till now, prefixSum[i] – prefixSum[j] + current element) as the prefixSum[i] – prefixSum[j] will give us the sum between index i and j.
  7. Update the last occurrence of current element to index i+1.

Below is the implementation of the above approach: 




#include <bits/stdc++.h>
using namespace std;
 
int maxSumUniqueSubarray(int* arr,int n)
{
      // Create the prefix sum array
    vector<int> preSum(n + 1);
 
    preSum[0] = 0;
 
    for (int i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + arr[i - 1];
   
      // Create an hashset containing the index of last occurrence of an element
    vector<int> lastSeen(1e4+1, 0);
   
      // Initialize the resultant global maximum sum with 0.
    int res = 0;
   
      // Initialize two pointers i and j at index 0
      // Traverse the array with the pointer i.
      int j = 0;
    for (int i = 0; i < n; i++)
    {
        int num = arr[i];
       
          // If the current element has occurred before,
          // reinitialize j with the maximum value between j and
          // the last occurrence of the current element.
        if (lastSeen[num] > 0)
        {
            j = max(j, lastSeen[num]);
        }
       
       
          // Update the resultant global maximum sum
        res = max(res, preSum[i] + num - preSum[j]);
       
          // Update the last occurrence of current element to index i+1.
        lastSeen[num] = i + 1;
    }
 
    return res;
}
// Driver Code
int  main()
{
  // Given array arr[]
  int arr[] = {1, 2, 3, 1, 5};
 
  // Function Call
  int ans = maxSumUniqueSubarray(arr, 5);
 
  // Print the maximum sum
  cout << (ans);
}
 
// This code is contributed by akashkumarsen4




import java.io.*;
import java.lang.*;
 
class GFG {
 
  static int maxSumUniqueSubarray(int[] arr, int n)
  {
    int[] preSum = new int[n+1];
 
    //ArrayList<Integer> preSum = new ArrayList<Integer>(n+1); 
    preSum[0] = 0;
 
    for (int i = 1; i <= n; i++)
    {
      preSum[i] = preSum[i-1]+arr[i-1];
    }
 
    // Create an hashset containing the index of last occurrence of an element
    int[] lastSeen = new int[10001];
 
    // Initialize the resultant global maximum sum with 0.
    int res = 0;
 
    // Initialize two pointers i and j at index 0
    // Traverse the array with the pointer i.
    int j = 0;
    for (int i = 0; i < n; i++)
    {
      int num = arr[i];
 
      // If the current element has occurred before,
      // reinitialize j with the maximum value between j and
      // the last occurrence of the current element.
      if (lastSeen[num] > 0)
      {
        j = Math.max(j, lastSeen[num]);
      }
 
      // Update the resultant global maximum sum
      res = Math.max(res, (preSum[i] + num - preSum[j]));
 
      // Update the last occurrence of current element to index i+1.
      lastSeen[num] = i+1;
    }
 
    return res;
  }
  public static void main(String[] args)
  {
 
    // Given array arr[]
    int[] arr = {1, 2, 3, 1, 5};
 
    // Function Call
    int ans = maxSumUniqueSubarray(arr, 5);
 
    // Print the maximum sum
    System.out.println(ans);
  }
 
}
 
// This code is contributed by aditya942003patil




def maxSumUniqueSubarray(arr, n):
    # Create the prefix sum array
    preSum = [0] * (n + 1)
 
    preSum[0] = 0
 
    for i in range(1, n + 1):
        preSum[i] = preSum[i - 1] + arr[i - 1]
 
    # Create an hashset containing the index of last occurrence of an element
    lastSeen = [0] * (10 ** 4 + 1)
 
    # Initialize the resultant global maximum sum with 0.
    res = 0
 
    # Initialize two pointers i and j at index 0
    # Traverse the array with the pointer i.
    j = 0
    for i in range(n):
        num = arr[i]
 
        # If the current element has occurred before,
        # reinitialize j with the maximum value between j and
        # the last occurrence of the current element.
        if lastSeen[num] > 0:
            j = max(j, lastSeen[num])
 
        # Update the resultant global maximum sum
        res = max(res, preSum[i] + num - preSum[j])
 
        # Update the last occurrence of current element to index i+1.
        lastSeen[num] = i + 1
 
    return res
 
# Given array arr[]
arr = [1, 2, 3, 1, 5]
 
# Function Call
ans = maxSumUniqueSubarray(arr, 5)
 
# Print the maximum sum
print(ans)




using System;
using System.Collections.Generic;
 
namespace ConsoleApp1 {
  class Program {
    static int maxSumUniqueSubarray(int[] arr, int n)
    {
      // Create the prefix sum array
      var preSum = new int[n + 1];
 
      preSum[0] = 0;
 
      for (int i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + arr[i - 1];
 
      // Create an hashset containing the index of last
      // occurrence of an element
      var lastSeen = new int[10000 + 1];
 
      // Initialize the resultant global maximum sum with
      // 0.
      int res = 0;
 
      // Initialize two pointers i and j at index 0
      // Traverse the array with the pointer i.
      int j = 0;
      for (int i = 0; i < n; i++) {
        int num = arr[i];
 
        // If the current element has occurred before,
        // reinitialize j with the maximum value between
        // j and the last occurrence of the current
        // element.
        if (lastSeen[num] > 0) {
          j = Math.Max(j, lastSeen[num]);
        }
 
        // Update the resultant global maximum sum
        res = Math.Max(res,
                       preSum[i] + num - preSum[j]);
 
        // Update the last occurrence of current element
        // to index i+1.
        lastSeen[num] = i + 1;
      }
 
      return res;
    }
 
    static void Main(string[] args)
    {
      // Given array arr[]
      int[] arr = { 1, 2, 3, 1, 5 };
 
      // Function Call
      int ans = maxSumUniqueSubarray(arr, 5);
 
      // Print the maximum sum
      Console.WriteLine(ans);
    }
  }
}
 
// This code is contributed by aadityamaharshi21.




// Javascript program for above approach
const maxSumUniqueSubarray = (arr, n) => {
    // Create the prefix sum array
    let preSum = [], lastSeen = [];
    preSum[0] = 0;
    for (let i = 1; i <= n; i++)
        preSum[i] = preSum[i - 1] + arr[i - 1];
 
    // Create an hashset containing the index of last occurrence of an element
    lastSeen = Array(10000 + 1).fill(0);
 
    // Initialize the resultant global maximum sum with 0.
    let res = 0;
 
    // Initialize two pointers i and j at index 0
    // Traverse the array with the pointer i.
    let j = 0;
    for (let i = 0; i < n; i++) {
        let num = arr[i];
 
        // If the current element has occurred before,
        // reinitialize j with the maximum value between j and
        // the last occurrence of the current element.
        if (lastSeen[num] > 0)
            j = Math.max(j, lastSeen[num]);
 
 
        // Update the resultant global maximum sum
        res = Math.max(res, preSum[i] + num - preSum[j]);
 
        // Update the last occurrence of current element to index i+1.
        lastSeen[num] = i + 1;
    }
 
    return res;
}
// Function Call
let arr = [1, 2, 3, 1, 5];
let ans = maxSumUniqueSubarray(arr, 5);
 
// Print the maximum sum
console.log(ans);
 
//   this is contributed by adityamaharshi21

Output
11

Time Complexity: O(N)
Auxiliary Space: O(MAX(N,max_element))


Article Tags :