I'm trying to figure out a way to iterativly select random values from an array, based on their weights. I'm going to use the example from here, but bear with me- this is a slightly different question. Here is a class representing a broker:
public class Broker
{
public string Name = string.Empty;
public int Weight = 0;
public Broker(string n, int w)
{
this.Name = n;
this.Weight = w;
}
}
Now, I have an array of brokers, and I want to randomly select a broker such that the probablity of Broker a to be selected equals a.Weight divided by the sum of all weights in the array.
The change here is that I want to do this n times, where n is the size of the array. So we can work with the numbers a little bit before starting (it's not gonna take less than O(n)). Also please note that the weights are of the same order of magnitude as n.
Here are the directions I thought of so far
- Build an array with a size that is the sum of all weights, and place each Broker a a.weights times in the array - then randomize a number between 0 and the size of the new array. The problem here - as mentioned, the weights are O(n), thus this is a O(n^2) algorithm.
- I found a way (which some might consider trivial) of solving this in O(nlog(n)). I assign each Broker the partial sum of weights, from the first and up to the previous broker. Then I draw a number from 0 to sum of weights, and find the broker with binary search. I could also have achieved this with balanced binary search trees.
Does anyone know of a better (i.e. O(n), or even O(log(log(n)))) solution? Or otherwise - can anyone prove we can't do it faster then O(nlog(n))?