最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教。

算法介绍

一、红包金额限制

      对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分。

//最小红包额度           


           private            static            final            int            MINMONEY =            1           ;           


           //最大红包额度           


           private            static            final            int            MAXMONEY =            200            *            100           ; 



二、判断红包金额是否合法      注意这一步伴随着整个算法,我们不仅要在分配红包之前要判断金额是否合法,同样要在每个人暂定随机金额后也要判断剩余的金额是否合法。

private            boolean            isRight(           int            money,            int            count) {           


                      double            avg = money / count;           


                      if            (avg < MINMONEY) {           


                      return            false           ;           


                      }           


                      if            (avg > MAXMONEY) {           


                      return            false           ;           


                      }           


                      return            true           ;           


           } 



三、随机产生一个红包      这里我们采用随机的方式产生一个在MINMONEY和MAXMONEY之间的一个红包,产生红包之后,我们需要判断剩余的钱是否是合法红包,如果不是合法红包,我们就重新产生分配方案,在重新产生分配方案的时候,我们需要确定一个事情,是产生的红包过大还是过小,如果红包过大,下次就随机一个小值到本次红包金额的一个红包,如果红包金额过小,我们就产生一个红包金额到大值的一个红包。

private            int            random(           int            money,            int            minS,            int            maxS,            int            count) {           


                      //红包数量为1,直接返回金额           


                      if            (count ==            1           ) {           


                      return            money;           


                      }           


                      //如果最大金额和最小金额相等,直接返回金额           


                      if            (minS == maxS) {           


                      return            minS;           


                      }           


                      int            max = maxS > money ? money : maxS;           


                      //随机产生一个红包           


                      int            one = ((           int           )Math.rint(Math.random() * (max - minS) + minS)) % max +            1           ;           


                      int            money1 = money - one;           


                      //判断该种分配方案是否正确           


                      if            (isRight(money1, count -           1           )) {           


                      return            one;           


                      }            else            {           


                      double            avg = money1 / (count -            1           );           


                      if            (avg < MINMONEY) {           


                      //递归调用,修改红包最大金额           


                      return            random(money, minS, one, count);           


                      }           else            if            (avg > MAXMONEY) {           


                      //递归调用,修改红包最小金额           


                      return            random(money, one, maxS, count);           


                      }           


                      }           


                      return            one;           


           } 



四、实现红包分配      这里为了避免某一个红包占用大量资金,我们需要设定非最后一个红包的最大金额,我们把他设置为红包金额平均值的N倍;有了一、二、三中的方法,我们就可以来实现红包的分配了。

//每个红包最大是平均值的倍数           


           private            static            final            double            TIMES =            2.1           ;           


                      


           public            List<Integer> splitRedPackets(           int            money,            int            count) {           


                      if            (!isRight(money, count)) {           


                      return            null           ;           


                      }           


                      List<Integer> list =            new            ArrayList<Integer>();           


                      //红包最大金额为平均金额的TIMES倍           


                      int            max = (           int           ) (money * TIMES / count);           


                      max = max > MAXMONEY ? MAXMONEY : max;           


                      for            (           int            i =            0           ; i < count; i++) {           


                      int            one = random(money, MINMONEY, max, count - i);           


                      list.add(one);           


                      money -= one;           


                      }           


                      return            list;           


           } 



红包分配方案评估

      上面介绍了红包的基本算法,下面我们就对算法进行一次验证,假设有一个200元100份的红包,我们来看一下最后的分配方案。


完整代码


/**           


                      *@Description:           


                      */          


           package            com.lulei.weixin.util;           


                      


           import            java.util.ArrayList;           


           import            java.util.List;           


                      


           import            com.lulei.util.JsonUtil;           


                      


           public            class            RedPacketUtil {           


                      //最小红包额度           


                      private            static            final            int            MINMONEY =            1           ;           


                      //最大红包额度           


                      private            static            final            int            MAXMONEY =            200            *            100           ;           


                      //每个红包最大是平均值的倍数           


                      private            static            final            double            TIMES =            2.1           ;           


                      


                      /**           


                      * @param money           


                      * @param count           


                      * @return           


                      * @Author:lulei           


                      * @Description: 拆分红包           


                      */          


                      public            List<Integer> splitRedPackets(           int            money,            int            count) {           


                      if            (!isRight(money, count)) {           


                      return            null           ;           


                      }           


                      List<Integer> list =            new            ArrayList<Integer>();           


                      //红包最大金额为平均金额的TIMES倍           


                      int            max = (           int           ) (money * TIMES / count);           


                      max = max > MAXMONEY ? MAXMONEY : max;           


                      for            (           int            i =            0           ; i < count; i++) {           


                      int            one = random(money, MINMONEY, max, count - i);           


                      list.add(one);           


                      money -= one;           


                      }           


                      return            list;           


                      }           


                      


                      /**           


                      * @param money           


                      * @param minS           


                      * @param maxS           


                      * @param count           


                      * @return           


                      * @Author:lulei           


                      * @Description: 随机红包额度           


                      */          


                      private            int            random(           int            money,            int            minS,            int            maxS,            int            count) {           


                      //红包数量为1,直接返回金额           


                      if            (count ==            1           ) {           


                      return            money;           


                      }           


                      //如果最大金额和最小金额相等,直接返回金额           


                      if            (minS == maxS) {           


                      return            minS;           


                      }           


                      int            max = maxS > money ? money : maxS;           


                      //随机产生一个红包           


                      int            one = ((           int           )Math.rint(Math.random() * (max - minS) + minS)) % max +            1           ;           


                      int            money1 = money - one;           


                      //判断该种分配方案是否正确           


                      if            (isRight(money1, count -           1           )) {           


                      return            one;           


                      }            else            {           


                      double            avg = money1 / (count -            1           );           


                      if            (avg < MINMONEY) {           


                      //递归调用,修改红包最大金额           


                      return            random(money, minS, one, count);           


                      }           else            if            (avg > MAXMONEY) {           


                      //递归调用,修改红包最小金额           


                      return            random(money, one, maxS, count);           


                      }           


                      }           


                      return            one;           


                      }           


                      


                      /**           


                      * @param money           


                      * @param count           


                      * @return           


                      * @Author:lulei           


                      * @Description: 此种红包是否合法           


                      */          


                      private            boolean            isRight(           int            money,            int            count) {           


                      double            avg = money / count;           


                      if            (avg < MINMONEY) {           


                      return            false           ;           


                      }           


                      if            (avg > MAXMONEY) {           


                      return            false           ;           


                      }           


                      return            true           ;           


                      }           


                      


                      public            static            void            main(String[] args) {           


                      // TODO Auto-generated method stub           


                      RedPacketUtil util =            new            RedPacketUtil();           


                      System.out.println(JsonUtil.parseJson(util.splitRedPackets(           20000           ,            100           )));           


                      }           


           }



以上就是本文的全部内容,希望对大家学习java程序设计有所帮助。