概率算法
最近遇到的公司的优惠券的抽取的随机算法,需求如下:有一堆的优惠券,概率为1到100之间,概率为100的一定抽到, 概率不满100的,按照各自概率随机最多取出其中一个。我所用的思想是,先获取优惠券list,将概率100的全部取出,在剩下的list中根据各自的概率取出,不满100的券的总和若满100则按照概率一定会有一张,否则则有可能一张也抽不到。
//券池
public class WeightCoupon{
private String objId;
private int weight; // 概率
public WeightCoupon() {
}
public WeightCoupon(String objId, int weight) {
this.objId = objId;
this.weight = weight;
}
public String getObjId() {
return objId;
}
public void setObjId(String objId) {
this.objId = objId;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
public static final int FULL_RATE = 100;
/**
* 根据概率随机优惠券
*
* @return 优惠券列表
*/
public static List<WeightCoupon> randomCoupon(List<WeightCoupon> coupons) {
Random random = new Random();
List<WeightCoupon> result = new ArrayList<WeightCoupon>();
Iterator<WeightCoupon> iterator = coupons.iterator();
WeightCoupon coupon;
while (iterator.hasNext()) {
coupon = iterator.next();
int rate = coupon.getWeight(); // 概率
if (rate >= FULL_RATE) { // 概率100的放入结果集中
result.add(coupon);
iterator.remove();
} else { // 概率不满100的放入map做后续操作
String couponId = coupon.getObjId();
}
}
// 还有概率不满100的做后续操作
if (coupons.size() > 0) {
int rateSum = 0;
for (WeightCoupon weightCoupon : coupons) {
rateSum = rateSum + weightCoupon.getWeight();
}
// 打乱顺序
Collections.shuffle(coupons);
// List<Integer> rates = Arrays.asList(FULL_RATE, rateSum);
// rateSum = Collections.max(rates);
int randomRate = random.nextInt(rateSum);
int randomFull = random.nextInt(FULL_RATE);
int init = 0;
for (WeightCoupon weightCoupon : coupons) {
if (randomFull > rateSum) { // 加起来不满100的可能抽不到券,大于等于100的肯定能抽到
break;
} else { // 本身概率越大,随机数在此范围内的概率就越大
if (randomRate >= init && randomRate < init + weightCoupon.getWeight()) {
result.add(weightCoupon);
break;
}
}
init = init + weightCoupon.getWeight();
}
}
return result;
}