Given an array arr[] of N positive integers and a range [L, R], the task is to find the maximum subset-sum such that the difference between the maximum and minimum elements of the subset lies in the given range.
Examples:
Input: arr[] = {6, 5, 0, 9, 1}, L = 0, R = 3 Output: 15 Explanation: The subset {6, 9} of the given array has the difference between maximum and minimum elements as 3 which lies in the given range [0, 3] and the sum of the elements as 15 which is the maximum possible.
Input: arr[] = {5, 10, 15, 20, 25}, L = 1, R = 2 Output: 0 Explanation: There exist no valid subsets.
Approach: The given problem can be solved with the help of a Binary Search after sorting the given array. Below are the steps to follow:
- Sort the given array in non-decreasing order.
- Create a prefix sum array sum[] using the algorithm discussed here.
- Traverse the array using a variable i for all values of i in the range [0, N).
- For each i, find the index j of the largest integer such that arr[j] <= arr[i] + R. This can be done using the upper_bound function.
- Maintain a variable ans, which stores the maximum subset-sum. Initially, ans = 0.
- If the subarray arr[i, j] forms a valid subset, update the value of ans to the max of ans and sum of the subarray arr[i, j].
- The value stored in ans is the required answer.
Below is the implementation of the above approach:
CPP
#include <bits/stdc++.h>
using namespace std;
int maxSubsetSum(vector< int > arr, int L, int R)
{
int N = arr.size();
sort(arr.begin(), arr.end());
int sum[N + 1] = {};
int ans = 0;
for ( int i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + arr[i - 1];
}
for ( int i = 0; i < N; i++) {
int val = arr[i] + R;
auto ptr = upper_bound(
arr.begin(), arr.end(), val);
ptr--;
int j = ptr - arr.begin();
if ((arr[j] - arr[i] <= R)
&& (arr[j] - arr[i] >= L)) {
ans = max(ans, sum[j + 1] - sum[i]);
}
}
return ans;
}
int main()
{
vector< int > arr{ 6, 5, 0, 9, 1 };
int L = 0;
int R = 3;
cout << maxSubsetSum(arr, L, R);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int upperBound( int [] a, int low, int high, int element){
while (low < high){
int middle = low + (high - low)/ 2 ;
if (a[middle] > element)
high = middle;
else
low = middle + 1 ;
}
return low;
}
static int maxSubsetSum( int [] arr, int L, int R)
{
int N = arr.length;
Arrays.sort(arr);
int []sum = new int [N + 1 ];
int ans = 0 ;
for ( int i = 1 ; i <= N; i++) {
sum[i] = sum[i - 1 ] + arr[i - 1 ];
}
for ( int i = 0 ; i < N; i++) {
int val = arr[i] + R;
int ptr = upperBound(arr, 0 , N,val);
ptr--;
int j = ptr;
if ((arr[j] - arr[i] <= R)
&& (arr[j] - arr[i] >= L)) {
ans = Math.max(ans, sum[j + 1 ] - sum[i]);
}
}
return ans;
}
public static void main(String[] args)
{
int [] arr = { 6 , 5 , 0 , 9 , 1 };
int L = 0 ;
int R = 3 ;
System.out.print(maxSubsetSum(arr, L, R));
}
}
|
Python3
from functools import cmp_to_key
def cmp_sort(a, b):
return a - b
def InsertionIndex(nums, target, left):
low = 0
high = len (nums)
while (low < high):
mid = low + ((high - low) / / 2 )
if (nums[mid] > target or (left and target = = nums[mid])):
high = mid
else :
low = mid + 1
return low
def upper_bound(nums, target):
targetRange = [ - 1 , - 1 ]
leftIdx = InsertionIndex(nums, target, True )
if (leftIdx = = len (nums) or nums[leftIdx] ! = target):
return targetRange
targetRange[ 0 ] = leftIdx
targetRange[ 1 ] = InsertionIndex(nums, target, False ) - 1
return targetRange
def maxSubsetSum(arr, L, R):
N = len (arr)
arr.sort(key = cmp_to_key(cmp_sort))
sum = [ 0 for i in range (N + 1 )]
ans = 0
for i in range ( 1 ,N + 1 ):
sum [i] = sum [i - 1 ] + arr[i - 1 ]
for i in range (N):
val = arr[i] + R
ptr = upper_bound(arr, val)
j = ptr[ 1 ]
if ((arr[j] - arr[i] < = R) and (arr[j] - arr[i] > = L)):
ans = max (ans, sum [j + 1 ] - sum [i])
return ans
arr = [ 6 , 5 , 0 , 9 , 1 ]
L = 0
R = 3
print (maxSubsetSum(arr, L, R))
|
C#
using System;
class GFG {
static int upperBound( int [] a, int low, int high,
int element)
{
while (low < high) {
int middle = low + (high - low) / 2;
if (a[middle] > element)
high = middle;
else
low = middle + 1;
}
return low;
}
static int maxSubsetSum( int [] arr, int L, int R)
{
int N = arr.Length;
Array.Sort(arr);
int [] sum = new int [N + 1];
int ans = 0;
for ( int i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + arr[i - 1];
}
for ( int i = 0; i < N; i++) {
int val = arr[i] + R;
int ptr = upperBound(arr, 0, N, val);
ptr--;
int j = ptr;
if ((arr[j] - arr[i] <= R)
&& (arr[j] - arr[i] >= L)) {
ans = Math.Max(ans, sum[j + 1] - sum[i]);
}
}
return ans;
}
static void Main( string [] args)
{
int [] arr = { 6, 5, 0, 9, 1 };
int L = 0;
int R = 3;
Console.WriteLine(maxSubsetSum(arr, L, R));
}
}
|
Javascript
<script>
function InsertionIndex(nums, target, left)
{
let low = 0,
high = nums.length
while (low < high) {
const mid = low + Math.floor((high - low) / 2)
if (nums[mid] > target || (left && target === nums[mid]))
high = mid
else
low = mid + 1
}
return low
}
function upper_bound(nums, target) {
const targetRange = [-1, -1]
const leftIdx = InsertionIndex(nums, target, true )
if (leftIdx === nums.length || nums[leftIdx] != target)
return targetRange
targetRange[0] = leftIdx
targetRange[1] = InsertionIndex(nums, target, false ) - 1
return targetRange
}
function maxSubsetSum(arr, L, R) {
let N = arr.length;
arr.sort( function (a, b) { return a - b })
let sum = new Array(N + 1).fill(0);
let ans = 0;
for (let i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + arr[i - 1];
}
for (let i = 0; i < N; i++) {
let val = arr[i] + R;
let ptr = upper_bound(
arr, val);
let j = ptr[1]
if ((arr[j] - arr[i] <= R)
&& (arr[j] - arr[i] >= L)) {
ans = Math.max(ans, sum[j + 1] - sum[i]);
}
}
return ans;
}
let arr = [6, 5, 0, 9, 1];
let L = 0;
let R = 3;
document.write(maxSubsetSum(arr, L, R));
</script>
|
Time Complexity: O(N*log N) Auxiliary Space: O(N)
|