帶權重的隨機演算法的快速實現
阿新 • • 發佈:2019-01-27
假設為抽獎的情景,現在有好幾個獎項,而且權重不相同,權重大的抽到的概率要更大怎麼辦?
"特等獎":1, "一等獎":2, "二等獎":3, "三等獎":4, "參與獎":5
我們可以抽取一個權重列表{1,2,3,4,5},累加權重和,並給每個獎獲設定相應的隨機數區間.在權重和的區間內出一個隨機數,查詢對應隨機數區間的所對應的獎就可以了.就是這麼簡單!
看程式碼!
public static int getWeightRandom(List<Integer> weights) {
//在權重總和的值區間--索引值 mapMap<Integer, Integer> weightIndex = new TreeMap<>();
int weigntSum = 0;
//遍歷權重list,儲存在權重總和的值區間--索引值
for (int i = 0; i < weights.size(); i++) {
//上區間值
if(0 == i) {
weightIndex.put(1, 0);
}else {
weightIndex.put(weigntSum+1, i);
}
//下區間值
weigntSum += weights.get(i);
weightIndex.put(weigntSum, i);
}
/*String json = JsonKit.toJson(weightIndex);
System.out.println(json);*/
//生成隨機數
Random r = new Random();
int num = r.nextInt(weigntSum) + 1;
//根據生成的隨機數獲取值區間對應的索引值
RandomUtil util = new RandomUtil();
Integer index = util.getWeightIndex(weightIndex, num);
System.out.println(num + ":" + index+":"+weights.get(index));
//返回帶權重的列表索引
return index;
}
private Integer getWeightIndex(Map<Integer, Integer> weightIndex, int num) {
int keyIndex = 0;
//隨機數所在的值區間
for (Integer key : weightIndex.keySet()) {
if(num <= key) {
keyIndex = key;
break;
}
}
//找到值區間所在的索引
Integer index = weightIndex.get(keyIndex);
return index;
}
public static void main(String args[]) {
List<Integer> weights = new ArrayList<>();
weights.add(1);
weights.add(2);
weights.add(3);
weights.add(4);
weights.add(5);
for (int i = 0; i < 20; i++) {
getWeightRandom(weights);
}
System.exit(0);
}