题目:有金额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;
}
?>

浙公网安备 33010602011771号