Maximize point to reduce Array by replacing Subarray with its sum
Last Updated :
18 Sep, 2023
Given an array arr[] of size, N, the task is to maximize the score to reduce the array to a single element by replacing any subarray with its sum where the score of one such operation is the product of subarray length and the minimum value of that subarray.
Examples:
Input: N = 2, arr[] = {1, 5}
Output: 2
Explanation: Select subarray (0, 1). Then array arr[] become { 6 } and points earned = 2 * min(1, 5) = 2. Total points earned = 2
Input: N = 3, arr[] = {2, 3, 5}
Output: 14
Explanation: First select subarray (0, 1), then array arr[] become { 5, 5 } and points earned = 2 * min(2, 3) = 4. Select subarray (0, 1), then array arr[] become { 10 } and points earned = 2* min(5, 5) = 10. Total points earned = 4 + 10 =14.
Approach using Prefix Sum and DP (Memoization):
The Basic idea to solve this problem statement is to maintain a prefix sum array and obtain sum between range using DP (memoization).
Let there be three elements in the subarray {a, b, c} with b > a > c.
1st Case: If we include all the element at a time. array becomes {a+b+c}, points reward = 3*min(a, b, c) = 3*c.
2nd Case: Now, take two element at a time,
First select subarray(1, 2), array becomes (a, b+c), points reward = 2 * min(b, c) = 2*c
Now select subarray(0, 1), array becomes (a+b+c), points reward = 2 * min(a, b+c) = 2*a
Total points obtained = 2*c + 2*a
Now, points obtained in the 2nd case is more than points obtained in the first case as
a > c So 2*a > c. So it is optimal to not choose all of the three at a time and break it into two parts from b. This can be implemented with the help of dynamic programming to store the maximum possible point for a subarray [i, j] for avoiding repeated calculation.
Follow the steps mentioned below to implement the idea:
- Create a prefix sum array pre[] to obtain the sum between any range in O(1) time.
- Create a recursive function that takes i and j as parameters that determines the range of a group.
- Iterate from k = i to j to partition the given range into two groups.
- Call the recursive function for these groups.
- Suppose ans1and ans2 represents the total points obtained from the left and the right part respectively.
- Now for the current partition at index k, the potential answer will be ans1 + ans2 + 2* min(left element, right element) as seen from the above discussion.
- Now left element will be pre[k+1]-pre[i], the right element will be pre[j-1] - pre[k+1], which can be computed in O(1) time from the prefix sum array.
- The Maximum value obtained for the range 0 to N-1 is the required answer.
Below is the implementation of the above approach.
C++
// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
// dp array to store repeated state
long long dp[100][100];
// Function to find the maximum possible points
long long maxPoint(int i, int j, vector<long long>& arr,
vector<long long>& temp)
{
// Base case
if (i >= j)
return 0;
if (j - i == 1)
return 2 * min(arr[i], arr[j]);
if (dp[i][j] != -1)
return dp[i][j];
long long ans = 0;
for (int k = i; k < j; k++) {
// Points rewarded for left subarray
long long ans1 = maxPoint(i, k, arr, temp);
// Points rewarded for right subarray
long long ans2 = maxPoint(k + 1, j, arr, temp);
long long left_element = temp[k + 1] - temp[i];
long long right_element = temp[j + 1] - temp[k + 1];
long long total
= ans1 + ans2
+ min(left_element, right_element) * 2;
// Total points for partition at current index
ans = max(total, ans);
}
// Store the ans in dp state and return the ans
return dp[i][j] = ans;
}
int findMax(vector<long long>& arr, int N)
{
vector<long long> temp;
temp.push_back(0);
// To store sum of each elements
long long s = 0;
for (int i = 0; i < N; i++) {
s += arr[i];
temp.push_back(s);
}
// Initializing DP array with -1
memset(dp, -1, sizeof(dp));
return maxPoint(0, N - 1, arr, temp);
}
// Driver Code
int main()
{
vector<long long> arr = { 2, 3, 5 };
int N = arr.size();
// Function call
int ans = findMax(arr, N);
cout << ans;
return 0;
}
Java
// Java code to implement the approach
public class gfg2
{
// dp array to store repeated state
static long[][] dp = new long[100][100];
// Function to find the maximum possible points
static long maxPoint(int i, int j, long[] arr,
long[] temp)
{
// Base case
if (i >= j)
return 0;
if (j - i == 1)
return 2 * Math.min(arr[i], arr[j]);
if (dp[i][j] != -1)
return dp[i][j];
long ans = 0;
for (int k = i; k < j; k++) {
// Points rewarded for left subarray
long ans1 = maxPoint(i, k, arr, temp);
// Points rewarded for right subarray
long ans2 = maxPoint(k + 1, j, arr, temp);
long left_element = temp[k + 1] - temp[i];
long right_element = temp[j + 1] - temp[k + 1];
long total
= ans1 + ans2
+ Math.min(left_element, right_element)
* 2;
// Total points for partition at current index
ans = Math.max(total, ans);
}
// Store the ans in dp state and return the ans
return dp[i][j] = ans;
}
static long findMax(long[] arr, int N)
{
// vector<long long> temp;
// temp.push_back(0);
long[] temp = new long[N + 1];
// To store sum of each elements
long s = 0;
for (int i = 0; i < N; i++) {
s += arr[i];
temp[i + 1] = s;
}
// Initializing DP array with -1
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[0].length; j++) {
dp[i][j] = -1;
}
}
return maxPoint(0, N - 1, arr, temp);
}
// Driver Code
public static void main(String[] args)
{
long[] arr = { 2, 3, 5 };
int N = arr.length;
// Function call
long ans = findMax(arr, N);
System.out.println(ans);
}
}
// This code is contributed by karandeep1234
Python3
#Python code to implement the approach
# dp array to store repeated state
dp=[[0 for i in range(100)] for j in range(100)]
# Function to find the maximum possible points
def maxPoint(i,j,arr,temp):
# Base case
if(i>=j):
return 0
if(j-i==1):
return 2 * min(arr[i], arr[j])
if(dp[i][j] != -1):
return dp[i][j]
ans=0
for k in range(i,j):
# Points rewarded for left subarray
ans1 = maxPoint(i, k, arr, temp)
# Points rewarded for right subarray
ans2 = maxPoint(k + 1, j, arr, temp)
left_element = temp[k + 1] - temp[i]
right_element = temp[j + 1] - temp[k + 1]
total=ans1 + ans2 + min(left_element, right_element) * 2
# Total points for partition at current index
ans = max(total, ans)
# Store the ans in dp state and return the ans
dp[i][j] = ans
return dp[i][j]
def findMax(arr,N):
temp=[]
temp.append(0)
# To store sum of each elements
s=0
for i in range(N):
s=s+arr[i]
temp.append(s)
# Initializing DP array with -1
for i in range(len(dp)):
for j in range(len(dp[0])):
dp[i][j]=-1
return maxPoint(0, N - 1, arr, temp)
# Driver Code
arr=[2,3,5]
N=len(arr)
# Function call
ans=findMax(arr,N)
print(ans)
# This code is contributed by Pushpesh Raj.
C#
// C# code to implement the approach
using System;
public class GFG {
// dp array to store repeated state
static long[, ] dp = new long[100, 100];
// Function to find the maximum possible points
static long maxPoint(int i, int j, long[] arr,
long[] temp)
{
// Base case
if (i >= j)
return 0;
if (j - i == 1)
return 2 * Math.Min(arr[i], arr[j]);
if (dp[i, j] != -1)
return dp[i, j];
long ans = 0;
for (int k = i; k < j; k++) {
// Points rewarded for left subarray
long ans1 = maxPoint(i, k, arr, temp);
// Points rewarded for right subarray
long ans2 = maxPoint(k + 1, j, arr, temp);
long left_element = temp[k + 1] - temp[i];
long right_element = temp[j + 1] - temp[k + 1];
long total
= ans1 + ans2
+ Math.Min(left_element, right_element)
* 2;
// Total points for partition at current index
ans = Math.Max(total, ans);
}
// Store the ans in dp state and return the ans
return dp[i, j] = ans;
}
static long findMax(long[] arr, int N)
{
// vector<long long> temp;
// temp.push_back(0);
long[] temp = new long[N + 1];
// To store sum of each elements
long s = 0;
for (int i = 0; i < N; i++) {
s += arr[i];
temp[i + 1] = s;
}
// Initializing DP array with -1
for (int i = 0; i < dp.GetLength(0); i++) {
for (int j = 0; j < dp.GetLength(1); j++) {
dp[i, j] = -1;
}
}
return maxPoint(0, N - 1, arr, temp);
}
static public void Main()
{
// Code
long[] arr = { 2, 3, 5 };
int N = arr.Length;
// Function call
long ans = findMax(arr, N);
Console.WriteLine(ans);
}
}
// This code is contributed by lokeshmvs21.
JavaScript
// JavaScript code to implement the approach
// dp array to store repeated state
var dp = [];
// Function to find the maximum possible points
function maxPoint(i, j, arr, temp) {
// Base case
if (i >= j)
return 0;
if (j - i == 1)
return 2 * Math.min(arr[i], arr[j]);
if (dp[i][j] != -1)
return dp[i][j];
var ans = 0;
for (var k = i; k < j; k++) {
// Points rewarded for left subarray
var ans1 = maxPoint(i, k, arr, temp);
// Points rewarded for right subarray
var ans2 = maxPoint(k + 1, j, arr, temp);
var left_element = temp[k + 1] - temp[i];
var right_element = temp[j + 1] - temp[k + 1];
var total = ans1 + ans2 + Math.min(left_element, right_element) * 2;
// Total points for partition at current index
ans = Math.max(total, ans);
}
// Store the ans in dp state and return the ans
return dp[i][j] = ans;
}
function findMax(arr, N) {
var temp = [];
temp.push(0);
// To store sum of each elements
var s = 0;
for (var i = 0; i < N; i++) {
s += arr[i];
temp.push(s);
}
// Initializing DP array with -1
for (var i = 0; i < 100; i++) {
dp[i] = [];
for (var j = 0; j < 100; j++) {
dp[i][j] = -1;
}
}
return maxPoint(0, N - 1, arr, temp);
}
// Driver Code
var arr = [2, 3, 5];
var N = arr.length;
// Function call
var ans = findMax(arr, N);
console.log(ans);
// This code is contributed by Tapesh(tapeshdua420)
Time complexity: O(N2)
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.
Below is the implementation of the code:
C++
// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
// Function to find the maximum possible points
int findMax(vector<long long>& arr, int N)
{
vector<long long> temp(N+1, 0);
// To store sum of each element
long long s = 0;
for (int i = 0; i < N; i++) {
s += arr[i];
temp[i+1] = s;
}
// Initializing DP array with 0
vector<vector<long long>> dp(N, vector<long long>(N, 0));
// Fill the DP table using tabulation
for (int len = 1; len < N; len++) {
for (int i = 0; i < N-len; i++) {
int j = i + len;
if (len == 1) {
dp[i][j] = 2 * min(arr[i], arr[j]);
} else {
for (int k = i; k < j; k++) {
long long ans1 = dp[i][k];
long long ans2 = dp[k+1][j];
long long left_element = temp[k+1] - temp[i];
long long right_element = temp[j+1] - temp[k+1];
long long total = ans1 + ans2 + 2 * min(left_element, right_element);
// Total points for partition at current index
dp[i][j] = max(dp[i][j], total);
}
}
}
}
// return the answer
return dp[0][N-1];
}
// Driver code
int main() {
vector<long long> arr = {2, 3, 5};
int N = arr.size();
// Function call
int ans = findMax(arr, N);
cout << ans;
return 0;
}
Java
import java.util.*;
public class MaxPossiblePoints {
static int findMax(List<Long> arr, int N) {
List<Long> temp = new ArrayList<>(Collections.nCopies(N + 1, 0L));
// To store sum of each element
long s = 0;
for (int i = 0; i < N; i++) {
s += arr.get(i);
temp.set(i + 1, s);
}
// Initializing DP array with 0
long[][] dp = new long[N][N];
// Fill the DP table using tabulation
for (int len = 1; len < N; len++) {
for (int i = 0; i < N - len; i++) {
int j = i + len;
if (len == 1) {
dp[i][j] = 2 * Math.min(arr.get(i), arr.get(j));
} else {
for (int k = i; k < j; k++) {
long ans1 = dp[i][k];
long ans2 = dp[k + 1][j];
long leftElement = temp.get(k + 1) - temp.get(i);
long rightElement = temp.get(j + 1) - temp.get(k + 1);
long total = ans1 + ans2 + 2 * Math.min(leftElement, rightElement);
// Total points for partition at the current index
dp[i][j] = Math.max(dp[i][j], total);
}
}
}
}
// Return the answer
return (int) dp[0][N - 1];
}
public static void main(String[] args) {
List<Long> arr = new ArrayList<>(Arrays.asList(2L, 3L, 5L));
int N = arr.size();
// Function call
int ans = findMax(arr, N);
System.out.println(ans);
}
}
// This code is contributed by Dwaipayan Bandyopadhyay
Python3
# Function to find the maximum possible points
def findMax(arr, N):
temp = [0] * (N+1)
# To store sum of each element
s = 0
for i in range(N):
s += arr[i]
temp[i+1] = s
# Initializing DP array with 0
dp = [[0] * N for _ in range(N)]
# Fill the DP table using tabulation
for length in range(1, N):
for i in range(N-length):
j = i + length
if length == 1:
dp[i][j] = 2 * min(arr[i], arr[j])
else:
for k in range(i, j):
ans1 = dp[i][k]
ans2 = dp[k+1][j]
left_element = temp[k+1] - temp[i]
right_element = temp[j+1] - temp[k+1]
total = ans1 + ans2 + 2 * min(left_element, right_element)
# Total points for partition at current index
dp[i][j] = max(dp[i][j], total)
# Returning result
return dp[0][N-1]
# Test case
arr = [2, 3, 5]
N = len(arr)
ans = findMax(arr, N)
print(ans)
C#
using System;
using System.Collections.Generic;
class GFG
{
// Function to find the maximum possible points
static int findMax(List<long> arr, int N)
{
List<long> temp = new List<long>(new long[N + 1]);
// To store sum of each element
long s = 0;
for (int i = 0; i < N; i++)
{
s += arr[i];
temp[i + 1] = s;
}
// Initializing DP array with 0
long[][] dp = new long[N][];
for (int i = 0; i < N; i++)
{
dp[i] = new long[N];
for (int j = 0; j < N; j++)
{
dp[i][j] = 0;
}
}
// Fill the DP table using tabulation
for (int len = 1; len < N; len++)
{
for (int i = 0; i < N - len; i++)
{
int j = i + len;
if (len == 1)
{
dp[i][j] = 2 * Math.Min(arr[i], arr[j]);
}
else
{
for (int k = i; k < j; k++)
{
long ans1 = dp[i][k];
long ans2 = dp[k + 1][j];
long left_element = temp[k + 1] - temp[i];
long right_element = temp[j + 1] - temp[k + 1];
long total = ans1 + ans2 + 2 * Math.Min(left_element, right_element);
// Total points for partition at current index
dp[i][j] = Math.Max(dp[i][j], total);
}
}
}
}
// return the answer
return (int)dp[0][N - 1];
}
// Driver code
static void Main(string[] args)
{
List<long> arr = new List<long> { 2, 3, 5 };
int N = arr.Count;
// Function call
int ans = findMax(arr, N);
Console.WriteLine(ans);
}
}
JavaScript
// Function to find the maximum possible points
function findMax(arr, N) {
let temp = new Array(N + 1).fill(0);
// To store sum of each element
let s = 0;
for (let i = 0; i < N; i++) {
s += arr[i];
temp[i + 1] = s;
}
// Initializing DP array with 0
let dp = new Array(N);
for (let i = 0; i < N; i++) {
dp[i] = new Array(N).fill(0);
}
// Fill the DP table using tabulation
for (let len = 1; len < N; len++) {
for (let i = 0; i < N - len; i++) {
let j = i + len;
if (len === 1) {
dp[i][j] = 2 * Math.min(arr[i], arr[j]);
} else {
for (let k = i; k < j; k++) {
let ans1 = dp[i][k];
let ans2 = dp[k + 1][j];
let left_element = temp[k + 1] - temp[i];
let right_element = temp[j + 1] - temp[k + 1];
let total = ans1 + ans2 + 2 * Math.min(left_element, right_element);
// Total points for partition at current index
dp[i][j] = Math.max(dp[i][j], total);
}
}
}
}
// return the answer
return dp[0][N - 1];
}
// test case
let arr = [2, 3, 5];
let N = arr.length;
let ans = findMax(arr, N);
console.log(ans);
Time complexity: O(N^2)
Auxiliary space: O(N^2)
Related Articles:
Similar Reads
Maximize non decreasing Array size by replacing Subarray with sum
Given an array arr[] of size N. In one operation only one subarray can be selected and replaced with the sum of the subarray. The task is to find the maximum size of the array after making it non-decreasing.Examples:Input: N = 5, arr[] = {5, 1, 6, 6, 6}Output: 4Explanation: maximum size non-decreasi
15+ min read
Maximize Array sum by replacing middle elements with min of Subarray corners
Given an array A[] of length N. Then your task is to output the maximum sum that can be achieved by using the given operation at any number of times (possibly zero): Select a subarray, whose length is at least 3.Replace all the middle elements (Except the first and last) with a minimum of elements a
7 min read
Maximize the sum of sum of the Array by removing end elements
Given an array arr of size N, the task is to maximize the sum of sum, of the remaining elements in the array, by removing the end elements.Example: Input: arr[] = {2, 3} Output: 3 Explanation: At first we will delete 2, then sum of remaining elements = 3. Then delete 3. Therefore sum of sum = 3 + 0
6 min read
Find maximum sum by replacing the Subarray in given range
Given an array arr[], the task is to find the maximum sum possible such that any subarray of the indices from [l, r] i.e all subarray elements from arr[l] to arr[r] can be replaced with |arr[l] - arr[r]| any number of times. Examples: Input: arr[] = { 9, 1}Output: 16Explanation: The subarray [l, r]
9 min read
Maximize array sum by replacing at most L elements to R for Q queries
Given an array arr[] consisting of N integers and an array Query[][] consisting of M pairs of the type {L, R}, the task is to find the maximum sum of the array by performing the queries Query[][] such that for each query {L, R} replace at most L array elements to the value R. Examples: Input: arr[]=
7 min read
Minimize Array Sum by replacing pairs with (X, Y) keeping their bitwise OR same
Given an array arr[] of size N. Find the minimum sum of the array after performing given operations any number of times: Select two different indices i, j (1 ⤠i < j ⤠N),Replace arr[i] and arr[j] with X and Y respectively (X, Y>0), such that arr[i] | arr[j] = X | Y, where | denotes the bitwis
5 min read
Maximize product of subarray sum with its minimum element
Given an array arr[] consisting of N positive integers, the task is to find the maximum product of subarray sum with the minimum element of that subarray. Examples: Input: arr[] = {3, 1, 6, 4, 5, 2}Output: 60Explanation:The required maximum product can be obtained using subarray {6, 4, 5}Therefore,
10 min read
Maximize deletions by removing prefix and suffix of Array with same sum
Given an array Arr[] of size N, the cost of removing ith element is Arr[i]. The task is to remove the maximum number of elements by removing the prefix and the suffix of the same length and having the same total cost. Examples: Input: Arr[] = {80, 90, 81, 80}Output: 2 Explanation: If we choose 80 fr
10 min read
Minimize cost for reducing array by replacing two elements with sum at most K times for any index
Given an array arr[] of size N and an integer K. The task is to find the minimum cost required to collect the sum of the array. The sum of the array is collected by picking any element and adding it to an element of any index in the array. The addition of elements at the same index is allowed for at
11 min read
Count maximum non-overlapping subarrays with given sum
Given an array arr[] consisting of N integers and an integer target, the task is to find the maximum number of non-empty non-overlapping subarrays such that the sum of array elements in each subarray is equal to the target. Examples: Input: arr[] = {2, -1, 4, 3, 6, 4, 5, 1}, target = 6Output: 3Expla
7 min read