Maximum sum subsequence with values differing by at least 2
Last Updated :
02 Oct, 2023
Given a positive integer array arr[] of size N, the task is to find the maximum sum of a subsequence with the constraint that no 2 numbers in the sequence should be adjacent to the value i.e. if arr[i] is taken into the answer, then neither occurrences of arr[i]-1 nor arr[i]+1 can be selected.
Examples:
Input: arr[] = {2, 2, 2}
Output: 6
Explanation:
The max sum subsequence will be [2, 2, 2] as it does not contain any occurrence of 1 or 3. Hence sum = 2 + 2 + 2 = 6
Input: arr[] = {2, 2, 3}
Output: 4
Explanation:
Subsequence 1: [2, 2] as it does not contain any occurrence of 1 or 3. Hence sum = 2 + 2 = 4
Subsequence 2: [3] as it does not contain any occurrence of 2 or 4. Hence sum = 3
Therefore, the max sum = 4
Solution Approach: The idea is to use Dynamic Programming, similar to this article.
- Create a map to store the number of times the element i appears in the sequence.
- To find the answer, it would be easy to first break the problem down into smaller problems. In this case, 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 numbers 0 and 1, then the solution would be to count[1]*1.
- Now build a recursive solution to this problem. For a sequence of numbers containing only the numbers, 0 to n, the choice is to either pick the Nth element or not.
dp[i] = max(dp[i – 1], dp[i – 2] + i*freq[i] )
dp[i-1] represents not picking the ith number, then the number before it can be considered.
dp[i – 2] + i*freq[i] represents picking the ith number, then the number before it is eliminated. Hence, the number before that is considered.
C++
#include <bits/stdc++.h>
using namespace std;
int get_max_sum( int arr[], int n)
{
unordered_map< int , int > freq;
for ( int i = 0; i < n; i++) {
freq[arr[i]]++;
}
int dp[100001];
memset (dp, 0, sizeof (dp));
dp[0] = 0;
dp[1] = freq[0];
for ( int i = 2; i <= 100000; i++) {
dp[i] = max(dp[i - 1],
dp[i - 2] + i * freq[i]);
}
return dp[100000];
}
int main()
{
int N = 3;
int arr[] = { 2, 2, 3 };
cout << get_max_sum(arr, N);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG{
public static int get_max_sum( int arr[], int n)
{
HashMap<Integer,
Integer> freq = new HashMap<Integer,
Integer>();
for ( int i = 0 ; i < n; i++)
{
if (freq.containsKey(arr[i]))
{
int x = freq.get(arr[i]);
freq.replace(arr[i], x + 1 );
}
else
freq.put(arr[i], 1 );
}
int [] dp = new int [ 100001 ];
for ( int i = 0 ; i < 100001 ; i++)
dp[i] = 0 ;
dp[ 0 ] = 0 ;
if (freq.containsKey( 0 ))
dp[ 1 ] = freq.get( 0 );
else
dp[ 1 ] = 0 ;
for ( int i = 2 ; i <= 100000 ; i++)
{
int temp = (freq.containsKey(i)) ?
freq.get(i) : 0 ;
dp[i] = Math.max(dp[i - 1 ],
dp[i - 2 ] + i * temp);
}
return dp[ 100000 ];
}
public static void main(String[] args)
{
int N = 3 ;
int arr[] = { 2 , 2 , 3 };
System.out.println(get_max_sum(arr, N));
}
}
|
Python3
from collections import defaultdict
def get_max_sum(arr, n):
freq = defaultdict( lambda : 0 )
for i in range (n):
freq[arr[i]] + = 1
dp = [ 0 ] * 100001
dp[ 0 ] = 0
dp[ 1 ] = freq[ 0 ]
for i in range ( 2 , 100000 + 1 ):
dp[i] = max (dp[i - 1 ],
dp[i - 2 ] + i * freq[i])
return dp[ 100000 ]
N = 3
arr = [ 2 , 2 , 3 ]
print (get_max_sum(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
public static int get_max_sum( int []arr, int n)
{
Dictionary< int ,
int > freq = new Dictionary< int ,
int >();
for ( int i = 0; i < n; i++)
{
if (freq.ContainsKey(arr[i]))
{
int x = freq[arr[i]];
freq[arr[i]]= x + 1;
}
else
freq.Add(arr[i], 1);
}
int [] dp = new int [100001];
for ( int i = 0; i < 100001; i++)
dp[i] = 0;
dp[0] = 0;
if (freq.ContainsKey(0))
dp[1] = freq[0];
else
dp[1] = 0;
for ( int i = 2; i <= 100000; i++)
{
int temp = (freq.ContainsKey(i)) ?
freq[i] : 0;
dp[i] = Math.Max(dp[i - 1],
dp[i - 2] + i * temp);
}
return dp[100000];
}
public static void Main(String[] args)
{
int N = 3;
int []arr = { 2, 2, 3 };
Console.WriteLine(get_max_sum(arr, N));
}
}
|
Javascript
<script>
function get_max_sum(arr, n)
{
var freq = new Map();
for ( var i = 0; i < n; i++) {
if (freq.has(arr[i]))
freq.set(arr[i], freq.get(arr[i])+1)
else
freq.set(arr[i], 1)
}
var dp = Array(100001).fill(0);
dp[0] = 0;
dp[1] = (freq.has(0)?freq.get(0):0);
for ( var i = 2; i <= 100000; i++) {
dp[i] = Math.max(dp[i - 1],
dp[i - 2] + i * (freq.has(i)?freq.get(i):0));
}
return dp[100000];
}
var N = 3;
var arr = [2, 2, 3];
document.write( get_max_sum(arr, N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Another approach : Without using DP array
In previous approach the current value dp[i[ is only depend only on the previous 2 values i.e. dp[i-1] and dp[i-2]. So to optimize the space complexity we can use variables to keep track of previous values.
Implementation Steps:
- Create 2 variables prev1 and prev2 to keep track o previous values of DP.
- Initialize base case prev1 = prev2 = 0.
- Create a variable curr to store current value.
- Iterate over subproblem using loop and update curr.
- After every iteration update prev1 and prev2 for further iterations.
- At last return curr.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int get_max_sum( int arr[], int n)
{
unordered_map< int , int > freq;
for ( int i = 0; i < n; i++) {
freq[arr[i]]++;
}
int prev1 = 0, prev2 = 0, curr = 0;
for ( int i = 1; i <= 100000; i++) {
curr = max(prev1, prev2 + i * freq[i]);
prev2 = prev1;
prev1 = curr;
}
return curr;
}
int main()
{
int N = 3;
int arr[] = { 2, 2, 3 };
cout << get_max_sum(arr, N);
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
public class Main {
static int getMaxSum( int [] arr, int n) {
Map<Integer, Integer> freq = new HashMap<>();
for ( int i = 0 ; i < n; i++) {
freq.put(arr[i], freq.getOrDefault(arr[i], 0 ) + 1 );
}
int prev1 = 0 , prev2 = 0 , curr = 0 ;
for ( int i = 1 ; i <= 100000 ; i++) {
curr = Math.max(prev1, prev2 + i * freq.getOrDefault(i, 0 ));
prev2 = prev1;
prev1 = curr;
}
return curr;
}
public static void main(String[] args) {
int N = 3 ;
int [] arr = { 2 , 2 , 3 };
System.out.println(getMaxSum(arr, N));
}
}
|
Python3
from collections import defaultdict
def get_max_sum(arr, n):
freq = defaultdict( int )
for i in range (n):
freq[arr[i]] + = 1
prev1 = 0
prev2 = 0
curr = 0
for i in range ( 1 , 100001 ):
curr = max (prev1, prev2 + i * freq[i])
prev2 = prev1
prev1 = curr
return curr
if __name__ = = '__main__' :
N = 3
arr = [ 2 , 2 , 3 ]
print (get_max_sum(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static int GetMaxSum( int [] arr, int n)
{
Dictionary< int , int > freq = new Dictionary< int , int >();
for ( int i = 0; i < n; i++)
{
if (!freq.ContainsKey(arr[i]))
{
freq[arr[i]] = 1;
}
else
{
freq[arr[i]]++;
}
}
int prev1 = 0, prev2 = 0, curr = 0;
for ( int i = 1; i <= 100000; i++)
{
curr = Math.Max(prev1, prev2 + i * (freq.ContainsKey(i) ? freq[i] : 0));
prev2 = prev1;
prev1 = curr;
}
return curr;
}
public static void Main()
{
int N = 3;
int [] arr = { 2, 2, 3 };
Console.WriteLine(GetMaxSum(arr, N));
}
}
|
Javascript
function getMaxSum(arr, n) {
const freq = new Map();
for (let i = 0; i < n; i++) {
freq.set(arr[i], (freq.get(arr[i]) || 0) + 1);
}
let prev1 = 0;
let prev2 = 0;
let curr = 0;
for (let i = 1; i <= 100000; i++) {
curr = Math.max(prev1, prev2 + i * (freq.get(i) || 0));
prev2 = prev1;
prev1 = curr;
}
return curr;
}
const arr = [2, 2, 3];
const n = 3;
console.log(getMaxSum(arr, n));
|
Output:
4
Time Complexity: O(N) for map
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...