題目:有金額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; } ?>