Count all subsets with given sum - Java - algorithm

I have an array list of distinct positive integers representing a set L, and an integer S. What's the fastest way to count all subsets of L which have the sum of their elements equal to S, instead of iterating over all subsets and just checking if each subset's sum equal is equal to S?

This can be solved in O(NS) using a simple dynamic programming approach, similar to knapsack problem. Let's for each Q and for each i solve the following problem: how many subsets of first i elements of L exist so that their sum is equal to Q. Let us denote the number of such subsets C[i,Q].
Obviously, C[0,0]=1 and C[0,Q]=0 for Q!=0. (Note that i=0 denotes first 0 elements, that is no elements.)
For a bigger i we have two possibilities: either the last available element (L[i-1]) is taken to our set, then we have C[i-1, Q-L[i-1]] such sets. Either it is not taken, then we have C[i-1, Q] such sets. Therefore, C[i,Q]=C[i-1, Q-L[i-1]]+C[i-1, Q]. Iterating over i and Q, we calculate all Cs.
Note that if all elements in L are non-negative, then you can solve the problem only for non-negative Qs, and the first term disappears if Q<L[i-1]. If negative elements are allowed, then you need to consider negative Qs too.

Related

Finding two sublists of fixed sizes (K,L) to maximize total sum among positive sequence

Given a list of positive integers, and two integers K and L, I need to select two non-overlapping contiguous sublists of lengths K and L so as to maximize the combined sum of the two sublists.
For example, if the list is [6,1,4,6,3,2,7,4], K = 3, and L = 2, then I want the sublists [4,6,3] and [7,4], whose combined sum of 24 is the maximum achievable.
The list has at least K + L elements and at most 600 elements; the elements are integers in the range [1, 500].
I do not know where to start. I'm thinking a Dynamic Programming solution, but I'm not very familiar with it so I'm not sure if that's the way to go.
Scan array left to right, calculating partial sums for continuous subarrays of length K and of length L starting at every index. It might be performed in O(n).
Write the largest sums before each index to auxiliary arrays LeftK, LeftL
Write the largest sums after each index to auxiliary arrays RightK, RightL
Now for every index i get sums of LeftK[i]+RightL[i] and LeftL[i]+RightK[i] and choose the best sum among all entries.

Finding smallest subarray lengths for given multiple queries

You are given an array of integers A[], of max length N, up to 10^6 and then M number of queries. While querying you will be given an integer X and you have to return minimum length of sub array whose sum is greater or equal to X. Problem is the number of such queries M can be up to 10^6.
any clue to solve it efficiently within contest time.
Note: When M is very small we can solve with O(M*N) but when M is huge I guess there must be different approach.
Note: There is a way to solve the problem here in O(N), when M =~ 1.

Given a set of n integers, list all possible subsets with sum>=k

Given an unsorted set of integers in the form of array, find all possible subsets whose sum is greater than or equal to a const integer k,
eg:- Our set is {1,2,3} and k=2
Possible subsets:-
{2},
{3},
{1,2},
{1,3},
{2,3},
{1,2,3}
I can only think of a naive algorithm which lists all the subsets of set and checks if sum of subset is >=k or not, but its an exponential algorithm and listing all subsets requires O(2^N). Can I use dynamic programming to solve it in polynomial time?
Listing all the subsets is going to be still O(2^N) because in the worst case you may still have to list all subsets apart from the empty one.
Dynamic programming can help you count the number of sets that have sum >= K
You go bottom-up keeping track of how many subsets summed to some value from range [1..K]. An approach like this will be O(N*K) which is going to be only feasible for small K.
The idea with the dynamic programming solution is best illustrated with an example. Consider this situation. Assume you know that out of all the sets composed of the first i elements you know that t1 sum to 2 and t2 sum to 3. Let's say that the next i+1 element is 4. Given all the existing sets we can build all the new sets by either appending the element i+1 or leaving it out. If we leave it out we get t1 subsets that sum to 2 and t2 subsets that sum to 3. If we append it then we obtain t1 subsets that sum to 6 (2 + 4) and t2 that sum to 7 (3 + 4) and one subset which contains just i+1 which sums to 4. That gives us the numbers of subsets that sum to (2,3,4,6,7) consisting of the first i+1 elements. We continue until N.
In pseudo-code this could look something like this:
int DP[N][K];
int set[N];
//go through all elements in the set by index
for i in range[0..N-1]
//count the one element subset consisting only of set[i]
DP[i][set[i]] = 1
if (i == 0) continue;
//case 1. build and count all subsets that don't contain element set[i]
for k in range[1..K-1]
DP[i][k] += DP[i-1][k]
//case 2. build and count subsets that contain element set[i]
for k in range[0..K-1]
if k + set[i] >= K then break inner loop
DP[i][k+set[i]] += DP[i-1][k]
//result is the number of all subsets - number of subsets with sum < K
//the -1 is for the empty subset
return 2^N - sum(DP[N-1][1..K-1]) - 1
Can I use dynamic programming to solve it in polynomial time?
No. The problem is even harder than #amit (in the comments) mentions. Finding if there exists a subset that sums to a specific k is the subset-sum problem, which is NP-hard. Instead you are asking for how many solutions are equal to a specific k, which is in the much more difficult class of P#. In addition, your exact problem is slightly more difficult since you want to not only count, but enumerate all the possible subsets for k and targets < k.
If k is 0, and every element of the set is positive then you have no choice but to output every possible subset, so the lower-bound to this problem is O(2N) -- the time taken to produce the output.
Unless you know something more about the value k that you haven't told us, there's no faster general solution that to just check every subset.

Sum Combination List

I need an algorithm for this problem:
Given a set of n natural numbers x1,x2,...,xn, a number S and k. Form the sum of k numbers picked from the set (a number can be pick many times) with sum S.
Stated differently: List every possible combination for S with Bounds: n<=256, x<=1000, k<=32
E.g.
problem instance: {1,2,5,9,11,12,14,15}, S=30, k=3
There are 4 possible combinations
S=1+14+15, 2+14+14, 5+11+15, 9+9+12.
With these bounds, it is unfeasible to use brute force but I think of dynamic programming is a good approach.
The scheme is: Table t, with t[m,v] = number of combinations of sum v formed by m numbers.
1. Initialize t[1,x(i)], for every i.
2. Then use formula t[m,v]=Sum(t[m-1,v-x(i)], every i satisfied v-x(i)>0), 2<=m<=k.
3. After obtaining t[k,S], I can trace back to find all the combinations.
The dilemma is that t[m,v] can be increase by duplicate commutative combinations e.g., t[2,16]=2 due to 16=15+1 and 1+15. Furthermore, the final result f[3,30] is large, due to 1+14+15, 1+15+14, ...,2+14+14,14+2+14,...
How to get rid of symmetric permutations? Thanks in advance.
You can get rid of permutations by imposing an ordering on the way you pick elements of x. Make your table a triple t[m, v, n] = number of combinations of sum v formed by m numbers from x1..xn. Now observe t[m, v, n] = t[m, v, n-1] + t[m-1, v-x_n, n]. This solves the permutation problem by only generating summands in reverse order from their appearance in x. So for instance it'll generate 15+14+1 and 14+14+2 but never 14+15+1.
(You probably don't need to fill out the whole table, so you should probably compute lazily; in fact, a memoized recursive function is probably what you want here.)

Subset sum for exactly k integers?

Following from these question Subset sum problem and Sum-subset with a fixed subset size I was wondering what the general algorithm for solving a subset sum problem, where we are forced to use EXACTLY k integers, k <= n.
Evgeny Kluev mentioned that he would go for using optimal for k = 4 and after that use brute force approach for k- 4 and optimal for the rest. Anyone could enlight what he means by a brute force approach here combined with optimal k=4 algo?
Perhaps someone knows a better, general solution?
The original dynamic programming algorithm applies, with a slight extension - in addition to remembering partial sums, you also need to remember number of ints used to get the sums.
In the original algorithm, assuming the target sum is M and there are n integers, you fill a boolean n x M array A, where A[i,m] is true iff sum m can be achieved by picking (any number of) from first i+1 ints (assuming indexing from 0).
You can extend it to a three dimensional array nxMxk, which has a similar property - A[i,m,l] is true iff, sum m can be achieved by picking exactly l from first i+1 ints.
Assuming the ints are in array j[0..n-1]:
The recursive relation is pretty similar - the field A[0,j[0],1] is true (you pick j[0], getting sum j[0] with 1 int (duh)), other fields in A[0,*,*] are false and deriving fields in A[i+1,*,*] from A[i,*,*] is also similar to the original algorithm: A[i+1,m,l] is true if A[i,m,l]is true (if you can pick m from first i ints, then obviously you can pick m from first i+1 ints) or if A[i, m - j[i+1], l-1] is true (if you pick j[i+1] then you increase the sum by j[i+1] and the number of ints by 1).
If k is small then obviously it makes sense to skip all of the above part and just iterate over all combinations of k ints and checking their sums. k<=4 indeed seems like a sensible threshold.

Resources