Efficient algorithm to find a the set of numbers in a range

algorithms

If I have an array of sorted numbers and every object is one of the numbers or multiplication. For example if the sorted array is [1, 2, 7] then the set is {1, 2, 7, 1*2, 1*7, 2*7, 1*2*7}. As you can see if there's n numbers in the sorted array, the size of the set is 2n-1.

My question is how can I find for a given sorted array of n numbers all the objects in the set so that the objects is in a given interval. For example if the sorted array is [1, 2, 3 ... 19, 20] what is the most efficient algorithm to find the objects that are larger than 1000 and less than 2500 (without calculating all the 2n-1 objects)?

Best Answer

To search for a "sweet spot" such as this, you generally use a priority queue. The idea being is that you have a list sorted by a specific requirement. The more similar a solution is to a requirement, the more likely it will be chosen from the priority queue to search for more solutions.

In this case, your solution would be a series of indices in which each pertains to a number in your array. So in other words for the solution 2*7, you'd have an array [1,2]. You could also use a binary number with n bits if you prefer. The priority queue, in order to determine which is best, it should mulitply all numbers referred to by the indices together. The sweet spot in this case is going to be the place where you are likely to find most solutions, so in this case it would be the average between the maximum and the minimum, 1750.

The algorithm goes as follows:

Add each number in its own solution array and add it to the priority queue.

Then, starting with the first (the closest to (maximum+minimum)/2), remove it from the priority queue and for each index not included in the solution, add it to the solution and reinsert into the priority queue.

If you find that the current product times each new number exceeds the maximum, you don't even add it to the queue. If it is less than the minimum, then you do nothing with it.

If it is within the minimum and the maximum, do something with it.

Continue until you have them all.

In this way, you're reducing your solution search for values near your average. You should be getting most of your solutions immediately this way, but in order to get them all, you will have to search the entire solution space 2^n-1.

Lets do a quick test for a small range of values [1,2,3,4]. I want to find all solutions whose values are between 10 and 12, then I'd first by adding all numbers in their own solution and putting them in the priority queue. The priority would then look like: [[4],[3],[2],[1]].

I take the first [4], and I append 3, 2, and 1 in their own solutions and add it to the priority queue. The priority queue then becomes:

[[4, 3], [4, 2], [4, 1], [4], [3], [2], [1]]

I see that I've already got my first value [4, 3]! Lets continue and see what happens:

[[4, 3, 1], [4, 2], [4, 1], [4], [3], [2], [1]]

Notice that [4, 3, 2] was too large and was not added. I found another solution [4, 3, 1]!

If something isn't clear ask and I'll try to clarify.

Hope that helps.