Algorithm to calculate permutations - algorithm

I'm aware of Heap's algorithm to calculate permutations of a given sequence, but what if I wanted to calculate the permutations of a k-elements subset for a given sequence N?
The solution I'm thinking of this time is a backtracking one, but it would need to generate a new sequence of sub-elements each time deleting one and recursively calling the permutation function. This sounds expensive and I would like to know if there's a better solution

Use an algorithm to generate combinations of size K from the set of N.
(Pick any from the SO question: Algorithm to return all combinations of k elements from n).
Using the result, apply Heap's Algorithm to create all permutations of this k-element subset (or another Algorithm to generate all possible permutations of a list).
Generate the next subset of size K and repeat (steps 1 and 2) until all subsets of size K have been enumerated.

Related

Maximally set-covering set of k elements

Given a universe of elements U={e_1....e_n}, I have a collection of subsets of these elements C={s_1...s_m}. Now given a positive integer k, I want to find a solution of k elements which cover a maximal number of subsets.
A concrete example: I have a collection of songs. each song is composed of notes. if i only know how to play k distinct notes - which k notes would allow me to play the maximal number of songs, and what is this maximal number?
How is this problem called?
Brute force approach:
First find all distinct permutations of size k from n.
Then for every permutation find ,number of subsets it cover.
And remember, if you are taking one element that cover subset 's_1' for example then you have to take all elements from that subset, else greedy approach will cover only some part of subset not whole.
And then pick that permutation which gives maximum answer.
But brute force approach only works when k is less than 10.
As the order goes exponentially and there is no better solution than this, thus this question goes to np_hard. It can be shown that that your problem reduces to vertex cover problem.
Consider subsets as trees and elements as nodes.
Now your problem is to select k elements such that it covers maximum number of trees fully.

Finding a maximal sorted subsequence

Assume that we're given a set of pairs S={(x_1,y_1),...,(x_n,y_n)} of integers. What is the most efficient way of computing a maximal sequence of elements (a_1,b_1),...,(a_m,b_m) in S with the property that
a_i <= a_{i+1}
b_i <= b_{i+1}
for i=1,...,m-1, i.e. the sequence is ordered with respect to both components. I can come up with a quadratic algorithm that does the following:
We sort the elements of S with respect to the first coordinate, giving (c_1,d_1),...,(c_n,d_n), where c_i <= c_{i+1}.
Using dynamic programming, for each (c_i,d_i) we compute the longest sequence ordered with respect to both components that ends in (c_i,d_i). This can be done in linear time, once we know the longest such sequence for (c_1,d_1)...,(c_{i+1},d_{i+1}).
Since we have to perform an O(nlogn) sort in step 1 and a linear search for each index in step 2, which is quadratic, we end up with a quadratic runtime.
I've been trying to figure out whether there's a faster, i.e. O(nlogn) way of generating the maximal sequence from having two sorts of the set S: one with respect to the first component, and one with respect to the second. Is this possible?
Yes, it is possible to do it O(n log n).
Let's sort the elements of the set in lexicographical order. The first components are ordered correctly now, so we can forget about them.
Let's take a look at any sorted subsequence of this sorted sequence. The second elements form an increasing subsequence. That's why we can just find the longest increasing subsequence in the sorted sequence for the second element of each pair(completely ignoring first elements as they are already sorted properly). The longest increasing subsequence for an array of numbers can be found in O(n log n) time(it is a well-known problem).

How to generate random permutations fast

I read a question in an algorithm book:
"Given a positive integer n, choose 100 random permutations of [1,2,...,n],..."
I know how to generate random permutations with Knuth's algorithm. but does there exist any fast algorithms to generate large amount of permutations ?
Knuth shuffles require you to do n random swaps for a permutation of n elements (see http://en.wikipedia.org/wiki/Random_permutation#Knuth_shuffles) so the complexity is O(n) which is about the best you can expect if you receive a permutation on n elements.
Is this causing you a practical problem? If so, perhaps you could look at what you are doing with all those permutations in practice. Apart from simply getting by on less, you could think about deferring generating a permutation until you are sure you need it. If you need a permutation on n objects but only look at k of those n objects, perhaps you need a scheme for generating only those k elements. For small k, you could simply generate k random numbers in the range [0, n) at random, repeating generations which return numbers which have already come up. For small k, this would be unlikely.
There exist N! permutations of numbers from 1 to N. If you sort them lexicographically, like in a dictionary, it's possible to construct permutation knowing it order in a list of sorted permutations.
For example, let N=3, lexicographically sorted list of permutations is {123,132,213,231,312,321}. You generate number between 1 and 3!, for example 5. 5-th permutaion is 312. How to construct it?
Let's find the 1-st number of 5-th permutation. Let's divide permutations into blocks, criteria is 1-st number, I means such groups - {123,132},{213,231},{312,321}. Each group contains (n-1)! elements. The first number of permutation is the block number. 5-th permutation is in ceil(5/(3-1)!)=3 block. So, we've just found the first number of 5-th permutation it's 3.
Now I'm looking for not 5-th but (5-(n-1)!*(ceil(5/2)-1))=5-2*2=1-th permutation in
{3,1,2},{3,2,1}. 3 is determined and the same for all group members, so I'm actually searching for 1-th permutation in {1,2},{2,1} and N now is 2. Again, next_num = ceil(1/(new_N-1)!) = 1.
Continue it N times.
Hope you got the idea. Complexity is O(N) - because you constructing permutation elements one by one with arithmetical tricks.
UPDATE
When you got next number by arithmetical opearions you should also keep used array and instead of X take X-th unused Complexity becomes NlogN because logN needed for getting X-th unused element

Finding a k element subset in a set of real numbers (Programming Pearls book)

I am solving problems from Column2 of Programming Pearls. I came across this problem:
"Given a set of n real numbers, a real number t, and an integer k, how quickly can you determine whether there exists a k-element subset of the set that sums to at most t?"
My solution is to sort the set of real numbers and then look at the sum for the first k elements. If this sum is less than or equal to t, then we know there exists at least one
set that satisfies the condition.
Is the solution correct?
Is there a better or different solution?
Note: Just to make it clear, do not assume the input to be already sorted.
Because you need only first k elements sorted as per your problem , I suggest following:-
Select the kth element in array using randomised select O(N)
Take sum of first k elements in array and check if its less than t
Time complexity O(N + k) = O(N) as k is O(N)
Randomized Selection
Note:- when k is very small as compared to N then max heap can be very efficient as the storage does not cost that much and it can solve problem in worst case O(Nlogk).

How to enumerate all k-combinations of a set by sum?

Suppose I have a finite set of numeric values of size n.
Question: Is there an efficient algorithm for enumerating the k-combinations of that set so that combination I precedes combination J iff the sum of the elements in I is less than or equal to the sum of the elements in J?
Clearly it's possible to simply enumerate the combinations and sort them according to their sums. If the set is large, however, brute enumeration of all combinations, let alone sorting, will be infeasible. If I'm only interested in obtaining the first m << choose(n,k) combinations ranked by sum, is it possible to obtain them before the heat death of the universe?
There is no polynomial algorithm for enumerating the set this way (unless P=NP).
If there was such an algorithm (let it be A), then we could solve the subset sum problem polynomially:
run A
Do a binary search to find the subset that sums closest to the desired number.
Note that step 1 runs polynomially (assumption) and step 2 runs in O(log(2^n)) = O(n).
Conclusion: Since the Subset Sum problem is NP-Complete, solving this problem efficiently will prove P=NP - thus there is no known polynomial solution to the problem.
Edit: Even though the problem is NP-Hard, getting the "smallest" m subsets can be done on O(n+2^m) by selecting the smallest m elements, generating all the subsets from these m elements - and choosing the minimal m of those. So for fairly small values of m - it might be feasible to calculate it.

Resources