Given an array arr[], the task is to find the maximum score of deleting an element where each element of the array can be deleted with the score of the element, but the constraint is if we delete arr[i], then arr[i] + 1 and arr[i] – 1 is gets automatically deleted with 0 scores.
Examples:
Input: arr[] = {7, 2, 1, 8, 3, 3, 6, 6}
Output: 27
Explanation:
Step 0: arr[] = 7 2 1 8 3 3 6 6, Score: 0
Step 1: arr[] = 7 1 8 3 6 6, Score: 3
Step 2: arr[] = 7 1 8 6 6, Score: 6
Step 3: arr[] = 7 8 6 6, Score: 7
Step 4: arr[] = 8 6, Score: 13
Step 5: arr[] = 8 Score: 19
Step 6: arr[] = [] Score: 27
Input: arr[] = 1 2 3
Output: 4
Approach: The idea is to use Dynamic Programming to solve this problem. The key observation of the problem is that for removing any element from the array the occurrence of the element and the value itself is the important factor.
Let’s take an example to understand the observation if the sequence was 4 4 5. Then, we have two choices to choose from 4 to 5. Now, on choosing 4, his score would be 4*2 = 8. On the other hand, if we choose 5, his score would be 5*1 = 5. Clearly, the maximal score is 8.
Hence, for the above sequence 4 4 5, freq[4] = 2, and freq[5] = 1.
Finally, to find the optimal score, it would be easy to first break the problem down into a smaller problem. In this case, we break the sequence into smaller sequences and find an optimal solution for it. For the sequence of numbers containing only 0, the answer would be 0. Similarly, if a sequence contains only the number 0 and 1, then the solution would be count[1]*1.
Recurrence Relation:
dp[i] = max(dp[i – 1], dp[i – 2] + i*freq[i])
Basically, we have 2 cases, either to pick an ith element and other is not to pick an ith element.
Case 1: If we pick the ith element, Maximum score till the ith element will be dp[i-2] + i*freq[i] (choosing ith element means deleting (i-1)th element)
Case 2: If we don’t pick the ith element, the Maximum Score till ith element will dp[i-1]
Now as We have to maximize the score, We will take the maximum of both.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findMaximumScore(vector< int > a, int n)
{
unordered_map< int , int > freq;
for ( int i = 0; i < n; i++) {
freq[a[i]]++;
}
vector< int > dp(*max_element(a.begin(),
a.end())
+ 1,
0);
dp[0] = 0;
dp[1] = freq[1];
for ( int i = 2; i < dp.size(); i++)
dp[i] = max(
dp[i - 1],
dp[i - 2] + freq[i] * i);
return dp[dp.size() - 1];
}
int main()
{
int n;
n = 3;
vector< int > a{ 1, 2, 3 };
cout << findMaximumScore(a, n);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int findMaximumScore( int []a, int n)
{
@SuppressWarnings ( "unchecked" )
HashMap<Integer,
Integer> freq = new HashMap();
for ( int i = 0 ; i < n; i++)
{
if (freq.containsKey(a[i]))
{
freq.put(a[i],
freq.get(a[i]) + 1 );
}
else
{
freq.put(a[i], 1 );
}
}
int []dp = new int [Arrays.stream(a).max().getAsInt() + 1 ];
dp[ 0 ] = 0 ;
dp[ 1 ] = freq.get( 1 );
for ( int i = 2 ; i < dp.length; i++)
dp[i] = Math.max(dp[i - 1 ],
dp[i - 2 ] +
freq.get(i) * i);
return dp[dp.length - 1 ];
}
public static void main(String[] args)
{
int n;
n = 3 ;
int []a = { 1 , 2 , 3 };
System.out.print(findMaximumScore(a, n));
}
}
|
Python3
from collections import defaultdict
def findMaximumScore(a, n):
freq = defaultdict ( int )
for i in range (n):
freq[a[i]] + = 1
dp = [ 0 ] * ( max (a) + 1 )
dp[ 0 ] = 0
dp[ 1 ] = freq[ 1 ]
for i in range ( 2 , len (dp)):
dp[i] = max (dp[i - 1 ],
dp[i - 2 ] +
freq[i] * i)
return dp[ - 1 ]
if __name__ = = "__main__" :
n = 3
a = [ 1 , 2 , 3 ]
print (findMaximumScore(a, n))
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG{
static int findMaximumScore( int []a, int n)
{
Dictionary< int ,
int > freq = new Dictionary< int ,
int >();
for ( int i = 0; i < n; i++)
{
if (freq.ContainsKey(a[i]))
{
freq[a[i]] = freq[a[i]] + 1;
}
else
{
freq.Add(a[i], 1);
}
}
int []dp = new int [a.Max() + 1];
dp[0] = 0;
dp[1] = freq[1];
for ( int i = 2; i < dp.Length; i++)
dp[i] = Math.Max(dp[i - 1],
dp[i - 2] +
freq[i] * i);
return dp[dp.Length - 1];
}
public static void Main(String[] args)
{
int n;
n = 3;
int []a = { 1, 2, 3 };
Console.Write(findMaximumScore(a, n));
}
}
|
Javascript
<script>
function findMaximumScore(a,n)
{
let freq = new Map();
for (let i = 0; i < n; i++)
{
if (freq.has(a[i]))
{
freq.set(a[i],
freq.get(a[i]) + 1);
}
else
{
freq.set(a[i], 1);
}
}
let dp = new Array(Math.max(...a)+1);
dp[0] = 0;
dp[1] = freq.get(1);
for (let i = 2; i < dp.length; i++)
dp[i] = Math.max(dp[i - 1],
dp[i - 2] +
freq.get(i) * i);
return dp[dp.length - 1];
}
let n = 3;
let a=[1, 2, 3];
document.write(findMaximumScore(a, n));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Another Approach Using Memoization:
C++
#include <bits/stdc++.h>
using namespace std;
int solve(vector< int > &arr, int i)
{
if (i >= arr.size())
{
return 0;
}
int currValue = arr[i];
int currSum = arr[i];
int index = i + 1;
while (index < arr.size() && arr[index] == currValue)
{
currSum += arr[i];
index++;
}
while (index < arr.size() && arr[index] == currValue + 1)
{
index++;
}
return max(currSum + solve(arr, index), solve(arr, i + 1));
}
int findMaximumScore(vector< int >& arr) {
int n = arr.size();
sort(arr.begin(), arr.end());
return solve(arr, 0);
}
int main()
{
int n;
n = 3;
vector< int > a{ 1, 2, 3 };
cout << findMaximumScore(a);
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class Main {
static int solve(ArrayList<Integer> arr, int i)
{
if (i >= arr.size())
{
return 0 ;
}
int currValue = arr.get(i);
int currSum = arr.get(i);
int index = i + 1 ;
while (index < arr.size()
&& arr.get(index) == currValue) {
currSum += arr.get(i);
index++;
}
while (index < arr.size()
&& arr.get(index) == currValue + 1 ) {
index++;
}
return Math.max(currSum + solve(arr, index),
solve(arr, i + 1 ));
}
static int findMaximumScore(ArrayList<Integer> arr)
{
int n = arr.size();
Collections.sort(arr);
return solve(arr, 0 );
}
public static void main(String[] args)
{
int n = 3 ;
ArrayList<Integer> a
= new ArrayList<>(Arrays.asList( 1 , 2 , 3 ));
System.out.println(findMaximumScore(a));
}
}
|
Python
def solve(arr, i):
if i > = len (arr):
return 0
currValue = arr[i]
currSum = arr[i]
index = i + 1
while index < len (arr) and arr[index] = = currValue:
currSum + = arr[i]
index + = 1
while index < len (arr) and arr[index] = = currValue + 1 :
index + = 1
return max (currSum + solve(arr, index), solve(arr, i + 1 ))
def find_maximum_score(arr):
arr.sort()
return solve(arr, 0 )
if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 ]
print (find_maximum_score(arr))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
static int Solve(List< int > arr, int i)
{
if (i >= arr.Count) {
return 0;
}
int currValue = arr[i];
int currSum = arr[i];
int index = i + 1;
while (index < arr.Count
&& arr[index] == currValue) {
currSum += arr[i];
index++;
}
while (index < arr.Count
&& arr[index] == currValue + 1) {
index++;
}
return Math.Max(currSum + Solve(arr, index),
Solve(arr, i + 1));
}
static int FindMaximumScore(List< int > arr)
{
arr.Sort();
return Solve(arr,
0);
}
static void Main()
{
List< int > a = new List< int >{ 1, 2, 3 };
Console.WriteLine(FindMaximumScore(a));
}
}
|
Javascript
function solve(arr, i) {
if (i >= arr.length) {
return 0;
}
let currValue = arr[i];
let currSum = arr[i];
let index = i + 1;
while (index < arr.length && arr[index] === currValue) {
currSum += arr[i];
index++;
}
while (index < arr.length && arr[index] === currValue + 1) {
index++;
}
return Math.max(currSum + solve(arr, index), solve(arr, i + 1));
}
function findMaximumScore(arr) {
const n = arr.length;
arr.sort((a, b) => a - b);
return solve(arr, 0);
}
const a = [1, 2, 3];
console.log(findMaximumScore(a));
|
Time complexity: O(n)
Auxiliary Space: O(m)