Imagine we have a set S = [a,b,c,d,e,f]. And we have a set N = [1,2,3].
How can we assign elements of S to elements of N in all possible combinations?
The desired result will hold something like this:
[1,[a]], [2,[b,c]], [3,[d,e,f]].
[1,[a]], [2,[b,c,d]],[3,[e,f]].
etc.
Is it a powerset generation problem or anything else? How can I find its complexity and space complexity?
How can I generate those subsets?
This problem is related to the powerset generation. You will get |N|^|S| possible mappings.
Related
I have N different arrays with different numbers of elements. I want know if there is a good algorithm to find same sequences of values.
For example:
a= 1,2,3,4,5,6,7,8
b= 9,10,13,5,6,7,13,12
c= 20,36,24,11,2,3,5,6,7,9,11
I want, as result, that all the three arrays have the sequence 5,6,7 in common. Any suggestion?
You can use Suffix Array and LCP or Suffix Trie to solve this problem. Check this tutorial : http://wcipeg.com/wiki/Longest_common_substring
It will work in O(NLogN) time, where N is summation of all the sequence's length.
if number of list is not big then you can use dynamic programming solution explained here: http://wcipeg.com/wiki/Longest_common_substring#Dynamic_programming_solution
I have a set of floating point values that I want to divide into two sets whose size differs at most by one element. Additionally, the difference of value sums between the two sets should be minimal. Optionally, if the number of elements is odd and the sums cannot be equal, the smaller set should have the larger sum.
That would be the optimal solution, but I only really need an exact solution on the subset size constraints. The difference of sums doesn't strictly need to be minimal, but should come close. Also I would prefer if the smaller set (if any) has the larger sum.
I realize this may be related to the partition problem, but it's not quite the same, or as strict.
My current algorithm is the following, though I wonder if there's a way to improve upon that:
arbitrarily divide the set into two sets of the same size (or 1 element size difference)
do
diffOfSums := sum1 - sum2
foundBetter := false
betterDiff := 0.0
foreach pair of elements from set1 and set2 do
if |diffOfSums - 2 * betterDiff| > |diffOfSums - 2 * (value1 - value2)| then
foundBetter := true
betterDiff := value1 - value2
endif
done
if foundBetter then swap the found elements
while foundBetter
My problem with this approach is that I'm not sure of the actual complexity and whether it can be improved upon. It certainly doesn't fulfill the requirement to leave the smaller subset with a larger sum.
Is there any existing algorithm that happens to do what I want to achieve? And if not, can you suggest ways for me to either improve my algorithm or figure out that it may already be reasonably good for the problem?
It easy to prove that the partition problem reduces to this problem in polynomial time.
Imagine you want to solve partition for some array A, but you only know how to solve your problem. You just have to double the array length, filling it with zeros. If you can solve it with your algorithm, then you have solved the partition problem. This proves your problem to be NP-hard.
But you'll see you can't reduce this problem to partition (i.e. it isn't NP-complete), unless you limit the precision of your floats. In that case the same algorithm would solve both.
In the general case, the best you can do is backtrack.
My suggestion would be to sort the values, then consider each pair of values (v1, v2), (v3, v4) putting one element from each pair into one partition.
The idea is to alternate putting the values into each set, so:
s1 = {v1, v4, v5, v8, . . . }
s2 = {v2, v3, v6, v7, . . . }
If there are an odd number of elements, put the last value into the set that best meets your conditions.
You have a relaxed definition of minimal, so a full search is unnecessary. The above should work quite well for many distributions of the values.
Given a set of n numbers; What is the code that generate all possible k-size subsets in descending order (decreasing each sum of values)?
Example:
Set={9,8,6,2,1} => n=5 and k=3. So the output is:
[9,8,6]
[9,8,2]
[9,8,1]
[9,6,2]
[9,6,1]
[8,6,2]
[8,6,1]
[9,2,1]
[8,2,1]
[6,2,1]
It is preferred the most efficient algorithm, but the algorithm with NP-Complete complexity (n choose k permutations) is the answer yet.
One-by-one generation in the Matlab Code is preferred for implementation. Or a solution that the maximum size of the ordered list in it can be determined (by this, for greater n and k, one may use an approximation and return specific size of this list without computing all possibilities).
Note: 1)Please give attention to the position of [9,2,1] in this ordered list. So index ordering is not the correct answer.
2)This may be a type of Lexicographical order.
Thanks to Divakar, Yvon, and Luis, one of the possible answers to this question:
There are sorted set combinations in the SSC, so
combs = nchoosek(Set,k);
[~,ind] = sort(sum(combs,2),'descend');
SSC = combs(ind,:);
if you want the index of each number array in the Set (has unique numbers), with num_arr index in SSC use this code
for i=1:k
Index(i)=find(SSC(num_arr,j)==Set(1,:));
end
this code returns [1,3,5] for [9,6,1] in Index.
for greater n
In this case, the computation is very time-consuming or even is impractical. An approximation may solves this issue, for such situations, you can find the first arbitrary answer by modifying the nchoosek.m in the Matlab.
I've come across this problem in a programming contest site and been trying different things for a few days but none of them seem to be efficient enough.
Here is the question: You are given a large array of integers and a number k. The goal is to divide the array into subarrays each containing no more than k elements, such that the sum of all the elements in all the sub arrays is maximal. Another condition is that none of these sub arrays can be adjacent to each other. In other words, we have to drop a few terms from the original array.
Its been bugging me for a while and would like to hear your perspective on approaching this problem.
Dynamic programming should do the trick. Short explanation why:
The key property of a problem susceptible to dynamic programming is that the optimal solution to the problem (here: the whole array) can always be expressed as composition of two optimal solutions to subproblems (here: two subarrays.) Not every split needs to have this property - it is sufficient for one such split to exist for any optimal solution.
Clearly if you split the optimal solution between arrays (on an element that has been dropped), then the subsolutions are optimal within both subarrays.
The algorithm:
Try every element of the array in turn as the splitting element, looking for the one that yields the best result. Solve the problem recursively for both parts of the array (the recursion stops when the subarray is no longer than k). Memoize solutions to avoid exponential time (the recursion will obviously try the same subarray many times.)
This is not a solution, but a clue.
Consider solving the following problem:
From an array X choose elements a subset of elements such that none of them are adjacent to each other and their sum is maximum.
Now, the above problem is a special case of your problem where K=1. Think how you can expand the solution to a general case. Let me know if you don't know how to solve the simpler case.
I don't have time to explain why this works and should be the accepted answer:
def maxK(a, k):
states = k+1
myList = [0 for i in range(states)]
for i in range(0, len(a)):
maxV = max (myList)
myList = [a[i] + j for j in myList]
myList[(states-i) % k] = maxV
return max(myList)
This works with negative numbers too. This is linear in size(a) times k. The language I used is Python because at this level it can be read as if it were pseudo code.
I'm writing a Digital Fountain system in C#. Part of this system creates me sets of integers, I need to find the combinations of sets which create can leave me with a set of just one item. What's the fastest way to do this?
Set A: 1,2,3,4,5,6
Set B: 1,2,3,4,6
Set C: 1,2,3
Set D: 5,6
Solutions:
A - B => 5
A - (C + D) => 4
I don't need to find all combinations, just enough to find me as many unique numbers as possible. This may be possible to exploit to create a more efficient algorithm.
An important point that I forgot to mention:
I do not know, beforehand, how many sets there are, instead I add them one by one, and must determine each time if I have found every number I require. So the algorithm must be something which can be run in stages as new sets are added.
Nb. Solutions in C# get bonus marks ;)
i think some nice solutions can be gained by some sort of modification of using greedy set cover (http://en.wikipedia.org/wiki/Set_cover_problem) algorithm.
[pseudocode]
so:
1. sort sets by size descending
2.
foreach set in sets do:
uncovered = set.size
while uncovered > 1
current_set = the biggest set that covers no more than (uncovered - 1) and was not used before to cover set
uncovered = uncovered - covered_by_set(set)
collect current_set to some array
end
end
edit:
you can ommit foreach loop for last
set
this will bring you no more than one
solution for each of sets (to fix
this you can change problem directly
into set cover problem and use greedy
set cover), for example if you array
[1,3,4], you need to find solution of
SCV problem for all subsets of it
that have size = 2: [1,3],
[1,4], [3,4]. it will make problem
much more complex
another way that you may consider are
evolution algorithms (representation
here will be very simple, treat
specified number as bit, fitness
function should grow closer to 1),
but this still don't solve problem of
adding new set after calculations
(maybe when you have best population
from last problem, then after adding
new set just add new place in
chromosome)