完全随机发红包的php算法实现 作者: 灯小笼 时间: 2018-10-18 分类: 开发 题目:有金额M元,给N个人发红包,最低0.01元,完全随机,不设上限,全部金额都需发放出去。 思路:可以借鉴发牌的算法,将金额以最小发放单位0.01元换算,等价于`M*100`张牌。那么我们要做的是,从`M*100`张牌里边随机抽出`N-1`张牌,计算这`N-1`张牌中间隔出来的`N`个区间的差值即可。 ```php $total = 100; $num = 10; $ret = assignMoney($total, $num); echo implode(',', $ret) . PHP_EOL; assert(array_sum($ret) == $total); /** * 发放红包 * @param $total 红包的总金额(单位:分) * @param $num 分红包的人数 * @return array 分配的红包的数组 */ function assignMoney($total, $num) { // 只有1个人分时,总是全部给他就行 if ($num == 1) { return [$total]; } // 如果总数和人数一样,则每人都得1分钱 if ($total == $num) { return array_fill(0, $num, 1); } // 将每一分钱排成1个数组 $moneys = []; for ($i = 0; $i < $total; $i++) { $moneys[] = $i + 1; } // 从中随机选出[总数-1]个元素 $indexs = []; $realNum = min($total, $num); $max = count($moneys) - 2; for ($i = 0; $i < $realNum - 1; $i++) { $index = random_int(0, $max); $indexs[] = $moneys[$index]; // 已选中的元素排除出去 $moneys[$index] = $moneys[$max]; $max--; } // 将选出的数组排好序 sort($indexs, SORT_NUMERIC); // 计算出每个元素间隔的元素个数,也就是需要发红包的数量 $ret = [$indexs[0]]; for ($i = 0; $i < $realNum - 2; $i++) { $ret[] = ($indexs[$i + 1] - $indexs[$i]); } $ret[] = $total - $indexs[$realNum - 2]; return $ret; } ``` 几次结果如下: ```bash 1,8,13,9,16,13,5,7,2,26 2,12,1,1,19,12,7,12,17,17 21,4,1,2,4,20,2,35,3,8 3,11,9,2,1,19,12,30,7,6 11,5,11,7,44,1,1,8,10,2 ``` 标签: php, 算法, 微信红包