Subset sum problem where Array sum is at most N
Last Updated :
16 Feb, 2023
Given an array arr[] of size N such that the sum of all the array elements does not exceed N, and array queries[] containing Q queries. For each query, the task is to find if there is a subset of the array whose sum is the same as queries[i].
Examples:
Input: arr[] = {1, 0, 0, 0, 0, 2, 3}, queries[] = {3, 7, 6}
Output:
Possible
Not Possible
Possible
Explanation: 3 is spossible. 6 can be obtained by the subset {1, 2, 3}
7 is greater than the sum of all array elements.
Input: arr[] = {0, 1, 2}, queries[] = {1, 2, 3, 0}
Output:
Possible
Possible
Possible
Possible
Explanation: All the sums can be obtained by using the elements.
Approach: The problem can be solved using the approach as in the subset sum problem.
However, the time complexity can be reduced using the fact that the sum can be at most N. As the sum can be at most N, it can be proved that there are at most √2N unique positive elements where all have a frequency of 1.
Say there are √2N unique positive elements starting from 1 to √2N.
Therefore the sum of those numbers is N + √(N/2).
This sum is more than N itself. So there can be at most √2N unique elements.
The above fact can be used and implemented in dynamic programming. Using coordinate compression all those unique elements can be stored in minimum space.
For each element check what is the minimum contribution of that element to achieve a sum j (j in the range [0, N]) or if it is not possible to achieve the sum j. The contribution of each item (say i) depends on the contribution of the other smaller items till the sum (j - i).
Follow the image shown below to understand better the difference of unused states for normal subset and when the sum is N at max:
Comparison:
Say the arr[] = {1, 2, 2, 2, 3, 3}. (Here sum is greater, so does not follow the condition of sum at most N. But here unique elements maintain the threshold. That's why it is used here just for understanding purpose)
Red cells signify the useless states, these are much more in traditional algorithm than optimized one.
Traditional Subset-Sum vs Frequency Optimized DP, Useless States
Follow the steps mentioned below to implement the approach;
- Use coordinate compression on all the unique elements.
- Build a 2D dp[][] array where dp[i][j] stores the contribution of ith item to get sum j. (If it is not possible then store -1, and if ith item is not needed then store 0 in dp[i][j]).
- Iterate from i = 0 to the maximum element:
- Iterate for j = 0 to N:
- If the value of dp[i][j-arr[i]] + 1 < dp[i][j] then update it.
- Otherwise, keep it as it was.
- Then iterate from i = 0 to Q:
- Check if that sum (query[i])is possible or not.
- It is not possible if it exceeds the array sum or all the elements together cannot get a certain sum i.e. dp[len][query[i]] = -1. (len is total number of unique elements)
Below is the implementation of the above approach.
C++
// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
// Function to find if the queries
// are possible or not
void findSol(vector<int>& arr,
vector<int>& queries)
{
int s = 0;
// Calculating sum of array
for (auto& item : arr) {
s += item;
}
// Coordinate compression,
// make frequency-value pairs
map<int, int> mp;
for (auto& item : arr) {
mp[item]++;
}
vector<int> val, freq;
// Frequency mapping
for (auto& x : mp) {
val.push_back(x.first);
freq.push_back(x.second);
}
int len = val.size();
vector<vector<int> > dp(len + 1,
vector<int>(
s + 1, 0));
for (int j = 1; j <= s; ++j) {
dp[0][j] = -1;
}
// Loop to build the dp[][]
for (int i = 1; i <= len; ++i) {
for (int j = 1; j <= s; ++j) {
int v = val[i - 1];
int f = freq[i - 1];
if (dp[i - 1][j] != -1) {
dp[i][j] = 0;
}
else if (j >= v
&& dp[i][j - v] != -1
&& dp[i][j - v] + 1 <= f) {
dp[i][j] = dp[i][j - v] + 1;
}
else {
dp[i][j] = -1;
}
}
}
// Answer queries
for (auto& q : queries) {
if (q > s || dp[len][q] == -1) {
cout << "Not Possible" << endl;
}
else {
cout << "Possible" << endl;
}
}
}
// Driver Code
int main()
{
vector<int> arr = { 1, 0, 0, 0, 0, 2, 3 };
vector<int> queries = { 3, 7, 6 };
// Function call
findSol(arr, queries);
return 0;
}
Java
// Java code to implement the approach
import java.util.*;
class GFG
{
// Function to find if the queries
// are possible or not
static void findSol(ArrayList<Integer> arr, ArrayList<Integer> queries)
{
int s = 0;
// Calculating sum of array
for (Integer item : arr) {
s += item;
}
// Coordinate compression,
// make frequency-value pairs
HashMap<Integer, Integer> mp = new HashMap<>();
for (Integer item : arr) {
if(mp.containsKey(item))
mp.put(item,mp.get(item)+1);
else
mp.put(item,1);
}
ArrayList<Integer> val = new ArrayList<Integer>();
ArrayList<Integer> freq = new ArrayList<Integer>();
// Frequency mapping
for (Map.Entry<Integer,Integer> x : mp.entrySet())
{
val.add(x.getKey());
freq.add(x.getValue());
}
int len = val.size();
int dp[][] = new int[len+1][s+1];
for (int j = 1; j <= s; ++j) {
dp[0][j] = -1;
}
// Loop to build the dp[][]
for (int i = 1; i <= len; ++i) {
for (int j = 1; j <= s; ++j) {
int v = val.get(i - 1);
int f = freq.get(i - 1);
if (dp[i - 1][j] != -1) {
dp[i][j] = 0;
}
else if (j >= v
&& dp[i][j - v] != -1
&& dp[i][j - v] + 1 <= f) {
dp[i][j] = dp[i][j - v] + 1;
}
else {
dp[i][j] = -1;
}
}
}
// Answer queries
for(Integer q:queries)
{
if (q > s || dp[len][q] == -1) {
System.out.println("Not Possible");
}
else {
System.out.println("Possible");
}
}
}
// Driver Code
public static void main(String[] args)
{
ArrayList<Integer> arr = new ArrayList<Integer>(
Arrays.asList(1, 0, 0, 0, 0, 2, 3 ));
ArrayList<Integer> queries = new ArrayList<Integer>(
Arrays.asList(3, 7, 6 ));
// Function call
findSol(arr, queries);
}
}
// This code is contributed by Pushpesh Raj.
Python3
# Python3 code to implement the approach
# Function to find if the queries
# are possible or not
def findSol(arr, queries):
# calculating sum of array
s = sum(arr)
# Coordinate compression,
# make frequency-value pairs
mp = dict()
for item in arr:
if item not in mp:
mp[item] = 1
else:
mp[item] += 1
val = []
freq = []
# Frequency mapping
for x in mp:
val.append(x)
freq.append(mp[x])
len_ = len(val)
dp = [[0 for i in range(s + 1)] for j in range(len_ + 1)]
for j in range(1, s + 1):
dp[0][j] = -1
# Loop to build dp[][]
for i in range(1, len_ + 1):
for j in range(1, s + 1):
v = val[i - 1]
f = freq[i - 1]
if dp[i - 1][j] != -1:
dp[i][j] = 0
elif j >= 0 and dp[i][j - v] != -1 and dp[i][j - v] + 1 <= f:
dp[i][j] = dp[i][j - v] + 1
else:
dp[i][j] = -1
# Answer queries
for q in queries:
if q > s or dp[len_][q] == -1:
print("Not Possible")
else:
print("Possible")
# Driver Code
arr = [1, 0, 0, 0, 0, 2, 3]
queries = [3, 7, 6]
# Function call
findSol(arr, queries)
# This code is contributed by phasing17
C#
// C# program to implement above approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to find if the queries
// are possible or not
public static void findSol(List<int> arr, List<int> queries)
{
int s = 0;
// Calculating sum of array
foreach (int item in arr){
s += item;
}
// Coordinate compression,
// make frequency-value pairs
SortedDictionary<int, int> mp = new SortedDictionary<int, int>();
foreach (int item in arr) {
if(mp.ContainsKey(item)){
mp[item] = mp[item] + 1;
}else{
mp.Add(item, 1);
}
}
List<int> val = new List<int>();
List<int> freq = new List<int>();
// Frequency mapping
foreach (KeyValuePair<int,int> x in mp)
{
val.Add(x.Key);
freq.Add(x.Value);
}
int len = val.Count;
int[,] dp = new int[len+1, s+1];
for (int j = 1; j <= s; ++j) {
dp[0, j] = -1;
}
// Loop to build the dp[][]
for (int i = 1; i <= len; ++i) {
for (int j = 1; j <= s; ++j) {
int v = val[i - 1];
int f = freq[i - 1];
if (dp[i - 1, j] != -1) {
dp[i, j] = 0;
}
else if (j >= v && dp[i, j - v] != -1 && dp[i, j - v] + 1 <= f) {
dp[i, j] = dp[i, j - v] + 1;
}
else{
dp[i, j] = -1;
}
}
}
// Answer queries
foreach(int q in queries)
{
if (q > s || dp[len, q] == -1) {
Console.Write("Not Possible\n");
}
else {
Console.Write("Possible\n");
}
}
}
// Driver Code
public static void Main(string[] args){
List<int> arr = new List<int>{
1, 0, 0, 0, 0, 2, 3
};
List<int> queries = new List<int>{
3, 7, 6
};
// Function call
findSol(arr, queries);
}
}
// This code is contributed by subhamgoyal2014.
JavaScript
<script>
// JavaScript code to implement the approach
// Function to find if the queries
// are possible or not
function findSol(arr,queries)
{
let s = 0;
// Calculating sum of array
for (let item of arr) {
s += item;
}
// Coordinate compression,
// make frequency-value pairs
let mp = new Map();
for (let item of arr) {
if(mp.has(item))
mp.set(item,mp.get(item)+1);
else mp.set(item,1);
}
let val = [], freq = [];
// Frequency mapping
for (let [x,y] of mp) {
val.push(x);
freq.push(y);
}
let len = val.length;
let dp = new Array(len + 1).fill(0).map(()=>new Array(s+1).fill(0));
for (let j = 1; j <= s; ++j) {
dp[0][j] = -1;
}
// Loop to build the dp[][]
for (let i = 1; i <= len; ++i) {
for (let j = 1; j <= s; ++j) {
let v = val[i - 1];
let f = freq[i - 1];
if (dp[i - 1][j] != -1) {
dp[i][j] = 0;
}
else if (j >= v
&& dp[i][j - v] != -1
&& dp[i][j - v] + 1 <= f) {
dp[i][j] = dp[i][j - v] + 1;
}
else {
dp[i][j] = -1;
}
}
}
// Answer queries
for (let q of queries) {
if (q > s || dp[len][q] == -1) {
console.log("Not Possible");
}
else {
console.log("Possible");
}
}
}
// Driver Code
let arr = [ 1, 0, 0, 0, 0, 2, 3 ];
let queries = [ 3, 7, 6 ];
// Function call
findSol(arr, queries);
// This code is contributed by shinjanpatra
</script>
OutputPossible
Not Possible
Possible
Time Complexity: O(N * √N)
Auxiliary Space: O(N * √N)
Similar Reads
Subset Sum Problem Given an array arr[] of non-negative integers and a value sum, the task is to check if there is a subset of the given array whose sum is equal to the given sum. Examples: Input: arr[] = [3, 34, 4, 12, 5, 2], sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9.Input: arr[] = [3, 34, 4
15+ min read
Subset sum in Different languages
Python Program for Subset Sum Problem | DP-25Write a Python program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum. Examples: Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9. Input:
7 min read
Java Program for Subset Sum Problem | DP-25Write a Java program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum. Examples: Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9. Input: se
8 min read
C Program for Subset Sum Problem | DP-25Write a C program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum. Examples: Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9. Input: set[]
8 min read
PHP Program for Subset Sum Problem | DP-25Write a PHP program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum. Examples: Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9. Input: set
7 min read
C# Program for Subset Sum Problem | DP-25Write a C# program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum. Examples: Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9Output: TrueExplanation: There is a subset (4, 5) with sum 9. Input: set[
8 min read
Subset Sum Problem using Backtracking Given a set[] of non-negative integers and a value sum, the task is to print the subset of the given set whose sum is equal to the given sum. Examples:Â Input:Â set[] = {1,2,1}, sum = 3Output:Â [1,2],[2,1]Explanation:Â There are subsets [1,2],[2,1] with sum 3. Input:Â set[] = {3, 34, 4, 12, 5, 2}, sum =
8 min read
Print all subsets with given sum Given an array arr[] of non-negative integers and an integer target. The task is to print all subsets of the array whose sum is equal to the given target. Note: If no subset has a sum equal to target, print -1.Examples:Input: arr[] = [5, 2, 3, 10, 6, 8], target = 10Output: [ [5, 2, 3], [2, 8], [10]
15+ min read
Subset Sum Problem in O(sum) space Given an array of non-negative integers and a value sum, determine if there is a subset of the given set with sum equal to given sum. Examples: Input: arr[] = {4, 1, 10, 12, 5, 2}, sum = 9Output: TRUEExplanation: {4, 5} is a subset with sum 9. Input: arr[] = {1, 8, 2, 5}, sum = 4Output: FALSE Explan
13 min read
Subset Sum is NP Complete Prerequisite: NP-Completeness, Subset Sum Problem Subset Sum Problem: Given N non-negative integers a1...aN and a target sum K, the task is to decide if there is a subset having a sum equal to K. Explanation: An instance of the problem is an input specified to the problem. An instance of the subset
5 min read
Minimum Subset sum difference problem with Subset partitioning Given a set of N integers with up to 40 elements, the task is to partition the set into two subsets of equal size (or the closest possible), such that the difference between the sums of the subsets is minimized. If the size of the set is odd, one subset will have one more element than the other. If
13 min read
Maximum subset sum such that no two elements in set have same digit in them Given an array of N elements. Find the subset of elements which has maximum sum such that no two elements in the subset has common digit present in them.Examples: Input : array[] = {22, 132, 4, 45, 12, 223} Output : 268 Maximum Sum Subset will be = {45, 223} . All possible digits are present except
12 min read
Find all distinct subset (or subsequence) sums of an array Given an array arr[] of size n, the task is to find a distinct sum that can be generated from the subsets of the given sets and return them in increasing order. It is given that the sum of array elements is small.Examples: Input: arr[] = [1, 2]Output: [0, 1, 2, 3]Explanation: Four distinct sums can
15+ min read
Subset sum problem where Array sum is at most N Given an array arr[] of size N such that the sum of all the array elements does not exceed N, and array queries[] containing Q queries. For each query, the task is to find if there is a subset of the array whose sum is the same as queries[i]. Examples: Input: arr[] = {1, 0, 0, 0, 0, 2, 3}, queries[]
10 min read