抽奖算法的具体实现

62 阅读2分钟

抽奖算法的具体实现

假设有 奖品A,中奖概率0.1 奖品B,中奖概率0.2 奖品C,中奖概率0.5 未中奖概率,0.2

如何来实现一个抽奖算法。

实现思路

第一时间想到的是构造一个100个数的空间。

抽奖其实就是抽到一个随机数。比如说抽到60,那么就是中了奖品C。抽到20,就是抽到了奖品B。 draw.png

public class AwardInfo{
  public String awardId;
  public BigDecimal awaradRate;
}

第一个方法:循环比对

如何确认奖品A就是分布在1-10上呢?

  1. 将所有奖品包括未中奖的中奖概率加在一起。计算得到中奖的分母因子。
  2. 将每个奖品的中奖概率除以分母因子乘以100即可。(这里的空间是1000,100000均可)
  3. 选中一个随机数,进行循环比对即可。

@Override
public String randomDraw(List<AwardInfo> list) {
  // 伪代码思路实现
  BigDecimal denominator = new BigDecimal(0);
  for(AwardInfo elem : list){
    denominator = elem.getAwaradRate() + denominator;
  }
  // 获取一个1-100的随机数
  Integer drawNum = getRandomNum(100);
  Integer curVal = 0;
  String targetAwardId;
  for(AwardInfo elem : list){
    Integer rateVal = elem.getAwaradRate().divide(denominator, 2, ROUND_UP);
    if(drawNum < rateVal + curVal){
      targetAwardId = elem.getAwardId();
      break;
    }
    curVal += rateVal;
  }
  // targetAwardId 就是中奖Id
}

这个算法的弊端在于,时间复杂度会随着奖品池的扩大而扩大。 但其实,我们计算完奖品分布图后,一眼就可以确定中奖的商品。

第二个方法:treemap/hashmap

很简单,只要将奖品信息存储在数据结构中。然后通过fun(drawNum)获取到对应的奖品信息既可以拿到中奖。

  1. 构造一颗100节点的红黑树/hashmap,每个节点存放奖品Id。
  2. 通过奖品Id直接拿到节点。

未中奖

对于未中奖,可以理解为抽到了一个特殊奖品。这样有利于统一抽象。