题目:有金额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); /** * 发放红包 */ 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; } ?>