Maximize sum of remaining elements after every removal of the array half with greater sum
Last Updated :
25 Apr, 2023
Given an array arr[] consisting of N integers, the task is to maximize the resultant sum obtained after adding remaining elements after every removal of the array half with maximum sum.
Array can be divided into two non-empty halves left[] and right[] where left[] contains the elements from the indices [0, N/2) and right[] contains the elements from the indices [N/2, N)
Examples:
Input: arr[] = {6, 2, 3, 4, 5, 5}
Output: 18
Explanation:
The given array is arr[] = {6, 2, 3, 4, 5, 5}
Step 1:
Sum of left half = 6 + 2 + 3 = 11
Sum of right half = 4 + 5 + 5 = 12
Resultant sum S = 11.
Step 2:
Modified array is arr[] = {6, 2, 3}
Sum of left half = 6
Sum of right half = 2 + 3 = 5
Resultant sum S = 11 + 5 = 16
Step 3:
Modified array is arr[] = {2, 3}
Sum of left half = 2
Sum of right half = 3
Resultant sum S = 16 + 2 = 18.
Therefore, the resultant sum is 18.
Input: arr[] = {4}
Output: 0
Naive Approach: The simplest approach to solve the problem is to use recursion. Below are the steps:
- Use the concept of prefix sum and initialize a variable, say res to store the final result.
- Create a dictionary.
- Traverse the array and store all the prefix sum in the dictionary.
- Now, iterate over the range [0, N] and store the prefix sum of left and right halves of the array as left and right respectively.
- Now, there are three possible conditions:
- left > right
- left < right
- left == right
- For all the above conditions, ignore the maximum sum and add the minimum among left and right sum to the resultant sum and continue the recursive calls.
- After all the recursive call ends, print the maximum value of the resultant sum.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
int maxweight( int s, int e,
unordered_map< int , int >& pre)
{
if (s == e)
return 0;
int ans = 0;
for ( int i = s; i < e; i++)
{
int left = pre[i] - pre[s - 1];
int right = pre[e] - pre[i];
if (left < right)
ans = max(ans, left +
maxweight(s, i, pre));
if (left == right)
{
ans = max({ans, left +
maxweight(s, i, pre),
right +
maxweight(i + 1, e, pre)});
}
if (left > right)
ans = max(ans, right +
maxweight(i + 1, e, pre));
}
return ans;
}
void maxSum(vector< int > arr)
{
unordered_map< int , int > pre;
pre[-1] = 0;
pre[0] = arr[0];
for ( int i = 1; i < arr.size(); i++)
{
pre[i] = pre[i - 1] + arr[i];
}
cout << maxweight(0, arr.size() - 1, pre);
}
int main()
{
vector< int > arr = { 6, 2, 3, 4, 5, 5 };
maxSum(arr);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int maxweight( int s, int e,
Map<Integer, Integer> pre)
{
if (s == e)
return 0 ;
int ans = 0 ;
for ( int i = s; i < e; i++)
{
int left = pre.get(i) - pre.get(s - 1 );
int right = pre.get(e) - pre.get(i);
if (left < right)
ans = Math.max(ans, left +
maxweight(s, i, pre));
if (left == right)
{
ans = Math.max(ans, Math.max(left +
maxweight(s, i, pre),
right + maxweight(i + 1 ,
e, pre)));
}
if (left > right)
ans = Math.max(ans, right +
maxweight(i + 1 , e, pre));
}
return ans;
}
static void maxSum(List<Integer> arr)
{
Map<Integer, Integer> pre = new HashMap<>();
pre.put(- 1 , 0 );
pre.put( 0 , arr.get( 0 ));
for ( int i = 1 ; i < arr.size(); i++)
{
pre.put(i, pre.getOrDefault(i - 1 , 0 ) +
arr.get(i));
}
System.out.println(maxweight( 0 ,
arr.size() - 1 , pre));
}
public static void main (String[] args)
{
List<Integer> arr = Arrays.asList( 6 , 2 , 3 ,
4 , 5 , 5 );
maxSum(arr);
}
}
|
Python3
def maxweight(s, e, pre):
if s = = e:
return 0
ans = 0
for i in range (s, e):
left = pre[i] - pre[s - 1 ]
right = pre[e] - pre[i]
if left < right:
ans = max (ans, left \
+ maxweight(s, i, pre))
if left = = right:
ans = max (ans, left \
+ maxweight(s, i, pre),
right \
+ maxweight(i + 1 , e, pre))
if left > right:
ans = max (ans, right \
+ maxweight(i + 1 , e, pre))
return ans
def maxSum(arr):
pre = { - 1 : 0 , 0 : arr[ 0 ]}
for i in range ( 1 , len (arr)):
pre[i] = pre[i - 1 ] + arr[i]
print (maxweight( 0 , len (arr) - 1 , pre))
arr = [ 6 , 2 , 3 , 4 , 5 , 5 ]
maxSum(arr)
|
Javascript
<script>
function maxweight(s, e, pre){
if (s == e)
return 0;
let ans = 0;
for (let i = s; i < e; i++)
{
if (!pre[i])
pre[i] = 0;
if (!pre[e])
pre[e] = 0;
if (!pre[s-1])
pre[s-1] = 0;
let left = pre[i] - pre[s - 1];
let right = pre[e] - pre[i];
if (left < right)
ans = Math.max(ans, left +
maxweight(s, i, pre));
if (left == right)
{
ans = Math.max(ans, Math.max(left +
maxweight(s, i, pre),
right +
maxweight(i + 1, e, pre)));
}
if (left > right)
ans = Math.max(ans, right +
maxweight(i + 1, e, pre));
}
return ans;
}
function maxSum(arr)
{
let pre = new Map;
pre[-1] = 0;
pre[0] = arr[0];
for (let i = 1; i < arr.length; i++)
{
pre[i] = pre[i - 1] + arr[i];
}
document.write( maxweight(0, arr.length - 1, pre));
}
arr = [ 6, 2, 3, 4, 5, 5 ];
maxSum(arr);
</script>
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int maxweight( int s, int e,
Dictionary< int ,
int > pre)
{
if (s == e)
return 0;
int ans = 0;
for ( int i = s; i < e; i++)
{
int left = pre[i] - pre[s - 1];
int right = pre[e] - pre[i];
if (left < right)
ans = Math.Max(ans, left +
maxweight(s, i, pre));
if (left == right)
{
ans = Math.Max(ans, Math.Max(left +
maxweight(s, i, pre),
right + maxweight(i + 1,
e, pre)));
}
if (left > right)
ans = Math.Max(ans, right +
maxweight(i + 1, e, pre));
}
return ans;
}
static void maxSum(List< int > arr)
{
Dictionary< int ,
int > pre = new Dictionary< int ,
int >();
pre.Add(-1, 0);
pre.Add(0, arr[0]);
for ( int i = 1; i < arr.Count; i++)
{
if (pre[i - 1] != 0)
pre.Add(i, pre[i - 1] + arr[i]);
else
pre.Add(i, arr[i]);
}
Console.WriteLine(maxweight(0,
arr.Count - 1, pre));
}
public static void Main(String[] args)
{
List< int > arr = new List< int >();
arr.Add(6);
arr.Add(2);
arr.Add(3);
arr.Add(4);
arr.Add(5);
arr.Add(5);
maxSum(arr);
}
}
|
Time Complexity: O(2N)
Auxiliary Space: O(N2)
Efficient Approach: To optimize the above approach, the idea is to observe that there are a number of repeated overlapping subproblems.
Therefore, for optimization, use Dynamic Programming. The idea is to use a dictionary and keep track of the result values so that when they are required in further computations it can be accessed without calculating them again.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[100][100];
int maxweight( int s, int e,
map< int , int > pre)
{
if (s == e)
return 0;
if (dp[s][e] != -1)
return dp[s][e];
int ans = 0;
for ( int i = s; i < e; i++)
{
int left = pre[i] - pre[s - 1];
int right = pre[e] - pre[i];
if (left < right)
ans = max(
ans, ( int )(left +
maxweight(s, i, pre)));
if (left == right)
ans = max(
ans, max(left + maxweight(s, i,
pre),
right + maxweight(i + 1,
e, pre)));
if (left > right)
ans = max(
ans, right + maxweight(i + 1, e, pre));
dp[s][e] = ans;
}
return dp[s][e];
}
void maxSum( int arr[], int n)
{
map< int , int > pre;
pre[-1] = 0;
pre[0] = arr[0];
memset (dp, -1, sizeof dp);
for ( int i = 0; i < n; i++)
pre[i] = pre[i - 1] + arr[i];
cout << (maxweight(0, n - 1, pre));
}
int main()
{
int arr[] = { 6, 2, 3, 4, 5, 5 };
maxSum(arr, 6);
}
|
Java
import java.util.*;
class solution{
static int [][] dp = new int [ 100 ][ 100 ];
static int maxweight( int s, int e,
HashMap<Integer, Integer> pre)
{
if (s == e)
return 0 ;
if (dp[s][e] != - 1 )
return dp[s][e];
int ans = 0 ;
for ( int i = s; i < e; i++)
{
int left = pre.get(i) -
pre.get(s - 1 );
int right = pre.get(e) -
pre.get(i);
if (left < right)
ans = Math.max(ans, ( int )(left +
maxweight(s, i, pre)));
if (left == right)
ans = Math.max(ans,
Math.max(left + maxweight(s, i,
pre),
right + maxweight(i + 1 ,
e, pre)));
if (left > right)
ans = Math.max(ans, right + maxweight(i + 1 ,
e, pre));
dp[s][e] = ans;
}
return dp[s][e];
}
static void maxSum( int arr[], int n)
{
HashMap<Integer,
Integer> pre = new HashMap<Integer,
Integer>();
pre.put(- 1 , 0 );
pre.put( 0 , arr[ 0 ]);
for ( int i = 0 ; i < 100 ; i++)
{
for ( int j = 0 ; j < 100 ; j++)
dp[i][j] = - 1 ;
}
for ( int i = 0 ; i < n; i++)
pre.put(i, pre.get(i - 1 ) + arr[i]);
System.out.print((maxweight( 0 , n - 1 , pre)));
}
public static void main(String args[])
{
int []arr = { 6 , 2 , 3 , 4 , 5 , 5 };
maxSum(arr, 6 );
}
}
|
Python3
def maxweight(s, e, pre, dp):
if s = = e:
return 0
key = (s, e)
if key in dp:
return dp[key]
ans = 0
for i in range (s, e):
left = pre[i] - pre[s - 1 ]
right = pre[e] - pre[i]
if left < right:
ans = max (ans, left \
+ maxweight(s, i, pre, dp))
if left = = right:
ans = max (ans, left \
+ maxweight(s, i, pre, dp),
right \
+ maxweight(i + 1 , e, pre, dp))
if left > right:
ans = max (ans, right \
+ maxweight(i + 1 , e, pre, dp))
dp[key] = ans
return dp[key]
def maxSum(arr):
pre = { - 1 : 0 , 0 : arr[ 0 ]}
dp = {}
for i in range ( 1 , len (arr)):
pre[i] = pre[i - 1 ] + arr[i]
print (maxweight( 0 , len (arr) - 1 , pre, dp))
arr = [ 6 , 2 , 3 , 4 , 5 , 5 ]
maxSum(arr)
|
Javascript
<script>
let dp=[];
for (let i = 0;i<100;i++){
dp[i] = [];
for (let j = 0;j<100;j++){
dp[i][j] = 0;
}
}
function maxweight( s, e, pre)
{
if (s == e)
return 0;
if (dp[s][e] != -1)
return dp[s][e];
let ans = 0;
for (let i = s; i < e; i++)
{
let left = pre[i] - pre[s - 1];
let right = pre[e] - pre[i];
if (left < right)
ans = Math.max(
ans, Number(left +
maxweight(s, i, pre)));
if (left == right)
ans = Math.max(
ans,Math. max(left + maxweight(s, i,
pre),
right + maxweight(i + 1,
e, pre)));
if (left > right)
ans = Math.max(
ans, right + maxweight(i + 1, e, pre));
dp[s][e] = ans;
}
return dp[s][e];
}
function maxSum(arr, n)
{
let pre = new Map();
pre[-1] = 0;
pre[0] = arr[0];
for (let i = 0;i<100;i++){
for (let j = 0;j<100;j++){
dp[i][j] = -1;
}
}
for (let i = 0; i < n; i++)
pre[i] = pre[i - 1] + arr[i];
document.write(maxweight(0, n - 1, pre));
}
let arr= [ 6, 2, 3, 4, 5, 5 ];
maxSum(arr, 6);
</script>
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int [,] dp = new int [100, 100];
static int maxweight( int s, int e,
Dictionary< int , int > pre)
{
if (s == e)
return 0;
if (dp[s, e] != -1)
return dp[s, e];
int ans = 0;
for ( int i = s; i < e; i++)
{
int left = pre[i] -
pre[s - 1];
int right = pre[e] -
pre[i];
if (left < right)
ans = Math.Max(ans, ( int )(left +
maxweight(s, i, pre)));
if (left == right)
ans = Math.Max(ans,
Math.Max(left + maxweight(s, i,
pre),
right + maxweight(i + 1,
e, pre)));
if (left > right)
ans = Math.Max(ans, right + maxweight(i + 1,
e, pre));
dp[s, e] = ans;
}
return dp[s, e];
}
static void maxSum( int []arr, int n)
{
Dictionary< int ,
int > pre = new Dictionary< int ,
int >();
pre.Add(-1, 0);
pre.Add(0, arr[0]);
for ( int i = 0; i < 100; i++)
{
for ( int j = 0; j < 100; j++)
dp[i, j] = -1;
}
for ( int i = 1; i < n; i++)
pre.Add(i, pre[i - 1] + arr[i]);
Console.Write((maxweight(0, n - 1, pre)));
}
public static void Main(String []args)
{
int []arr = { 6, 2, 3, 4, 5, 5 };
maxSum(arr, 6);
}
}
|
Time Complexity: O(N3)
Auxiliary Space: O(N2)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a table DP to store the solution of the subproblems.
- Initialize the table with base cases.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
- Return the final solution stored in dp[0][n-1].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int maxSum( int arr[], int n)
{
int pre[n+1];
pre[0] = 0;
for ( int i = 1; i <= n; i++)
pre[i] = pre[i-1] + arr[i-1];
int dp[n][n];
for ( int i = 0; i < n; i++)
dp[i][i] = 0;
for ( int len = 2; len <= n; len++) {
for ( int i = 0; i <= n-len; i++) {
int j = i + len - 1;
dp[i][j] = INT_MIN;
for ( int k = i; k < j; k++) {
int left_sum = pre[k+1] - pre[i];
int right_sum = pre[j+1] - pre[k+1];
if (left_sum < right_sum)
dp[i][j] = max(dp[i][j], left_sum + dp[i][k]);
else if (left_sum > right_sum)
dp[i][j] = max(dp[i][j], right_sum + dp[k+1][j]);
else
dp[i][j] = max(dp[i][j], max(left_sum +
dp[i][k], right_sum + dp[k+1][j]));
}
}
}
return dp[0][n-1];
}
int main()
{
int arr[] = {6, 2, 3, 4, 5, 5};
int n = sizeof (arr)/ sizeof (arr[0]);
cout << maxSum(arr, n) << endl;
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int maxSum( int [] arr, int n) {
int [] pre = new int [n+ 1 ];
pre[ 0 ] = 0 ;
for ( int i = 1 ; i <= n; i++)
pre[i] = pre[i- 1 ] + arr[i- 1 ];
int [][] dp = new int [n][n];
for ( int i = 0 ; i < n; i++)
dp[i][i] = 0 ;
for ( int len = 2 ; len <= n; len++) {
for ( int i = 0 ; i <= n-len; i++) {
int j = i + len - 1 ;
dp[i][j] = Integer.MIN_VALUE;
for ( int k = i; k < j; k++) {
int left_sum = pre[k+ 1 ] - pre[i];
int right_sum = pre[j+ 1 ] - pre[k+ 1 ];
if (left_sum < right_sum)
dp[i][j] = Math.max(dp[i][j], left_sum + dp[i][k]);
else if (left_sum > right_sum)
dp[i][j] = Math.max(dp[i][j], right_sum + dp[k+ 1 ][j]);
else
dp[i][j] = Math.max(dp[i][j], Math.max(left_sum +
dp[i][k], right_sum + dp[k+ 1 ][j]));
}
}
}
return dp[ 0 ][n- 1 ];
}
public static void main(String[] args) {
int [] arr = { 6 , 2 , 3 , 4 , 5 , 5 };
int n = arr.length;
System.out.println(maxSum(arr, n));
}
}
|
Python3
def maxSum(arr, n):
pre = [ 0 ] * (n + 1 )
for i in range ( 1 , n + 1 ):
pre[i] = pre[i - 1 ] + arr[i - 1 ]
dp = [[ 0 for j in range (n)] for i in range (n)]
for i in range (n):
dp[i][i] = 0
for length in range ( 2 , n + 1 ):
for i in range (n - length + 1 ):
j = i + length - 1
dp[i][j] = float ( '-inf' )
for k in range (i, j):
left_sum = pre[k + 1 ] - pre[i]
right_sum = pre[j + 1 ] - pre[k + 1 ]
if left_sum < right_sum:
dp[i][j] = max (dp[i][j], left_sum + dp[i][k])
elif left_sum > right_sum:
dp[i][j] = max (dp[i][j], right_sum + dp[k + 1 ][j])
else :
dp[i][j] = max (dp[i][j], max (left_sum + dp[i][k], right_sum + dp[k + 1 ][j]))
return dp[ 0 ][n - 1 ]
arr = [ 6 , 2 , 3 , 4 , 5 , 5 ]
n = len (arr)
print (maxSum(arr, n))
|
C#
using System;
public class MaxSumSubsequence
{
public static int MaxSum( int [] arr, int n)
{
int [] pre = new int [n+1];
pre[0] = 0;
for ( int i = 1; i <= n; i++)
pre[i] = pre[i-1] + arr[i-1];
int [,] dp = new int [n,n];
for ( int i = 0; i < n; i++)
dp[i,i] = 0;
for ( int len = 2; len <= n; len++) {
for ( int i = 0; i <= n-len; i++) {
int j = i + len - 1;
dp[i,j] = int .MinValue;
for ( int k = i; k < j; k++) {
int left_sum = pre[k+1] - pre[i];
int right_sum = pre[j+1] - pre[k+1];
if (left_sum < right_sum)
dp[i,j] = Math.Max(dp[i,j], left_sum + dp[i,k]);
else if (left_sum > right_sum)
dp[i,j] = Math.Max(dp[i,j], right_sum + dp[k+1,j]);
else
dp[i,j] = Math.Max(dp[i,j], Math.Max(left_sum + dp[i,k], right_sum + dp[k+1,j]));
}
}
}
return dp[0,n-1];
}
public static void Main()
{
int [] arr = {6, 2, 3, 4, 5, 5};
int n = arr.Length;
Console.WriteLine(MaxSum(arr, n));
}
}
|
Javascript
function maxSum(arr, n) {
let pre = new Array(n + 1);
pre[0] = 0;
for (let i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + arr[i - 1];
}
let dp = new Array(n);
for (let i = 0; i < n; i++) {
dp[i] = new Array(n);
}
for (let i = 0; i < n; i++) {
dp[i][i] = 0;
}
for (let len = 2; len <= n; len++) {
for (let i = 0; i <= n - len; i++) {
let j = i + len - 1;
dp[i][j] = Number.MIN_SAFE_INTEGER;
for (let k = i; k < j; k++) {
let left_sum = pre[k + 1] - pre[i];
let right_sum = pre[j + 1] - pre[k + 1];
if (left_sum < right_sum) {
dp[i][j] = Math.max(dp[i][j], left_sum + dp[i][k]);
} else if (left_sum > right_sum) {
dp[i][j] = Math.max(dp[i][j], right_sum + dp[k + 1][j]);
} else {
dp[i][j] = Math.max(dp[i][j], Math.max(left_sum + dp[i][k], right_sum + dp[k + 1][j]));
}
}
}
}
return dp[0][n - 1];
}
let arr = [6, 2, 3, 4, 5, 5];
let n = arr.length;
console.log(maxSum(arr, n));
|
Output
18
Time Complexity: O(N3)
Auxiliary Space: O(N2)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...