简介
是这个样子的,前段时间去面试,接近尾声时面试官突然提出这样一个问题:将一个100元的红包,分为20份,每份最低3元,最高不得超过6元;瞬间一脸懵B,之前确实是对算法这块有些生疏,再加上面试有些紧张,一时之间不知道该如何去解决;面试结束后就一直在想这个问题,五分钟不到就有了思路,害,不知道怎么说!另外这个问题现实场景中遇到的还是蛮多的,现在做一下记录,如果有更好的实现方法,欢迎交流!
解题思路
这道题从题面去理解: 类似于微信红包的意思,100分成20份,我们要知道关键的点在于如何去分, 首先要保证不能低于min值,其次要分完!
按照这个逻辑去推敲:
先保证第一个条件每个不能低于3元,声明一个数组保存20个value=3的元素;
上一步完成后,获取剩余金额,进行分配 100-(3*20) = 40;
只剩余40元可分配; 可用分支控制完成分配,两种思路 while foreach 当然你用其他的也可以!
代码
<?php
class redpackage
{
/**
* @param $money
* @param $package_number
* @param $min
* @param $max
* author: 划水小老虎
*/
function distribute($money,$package_number,$min,$max)
{
// 初始化数组
$base_array = [];
// 基础数组封装
$min_array = array_pad($base_array,$package_number,$min);
// 需要分的钱数
$wait_money = $money - ($min*$package_number);
// 最小随机数 此处是按照比例划分的 向上取整
$min_rand = ceil($wait_money / $package_number);
// 最大随机数
$max_rand = floor($max-$min-1);
// 维护算法的健壮性
if ($min*$package_number>$money) {
echo 'not much money 一分钱掰不成两个红包的!!!';
exit;
}
// 维护算法的健壮性
if ($min_rand>$max) {
echo 'Too much money 钱太多了 大佬!!!';
exit;
}
// 循环分赃
foreach ($min_array as $key=>&$value) {
$rand_num = $this->randMoney($min_rand,$max_rand);
$after_money = $wait_money - $rand_num;
// 判断剩余的钱数 是否小于0
if ($after_money>0) {
// 派发给小弟
$value = $value+$rand_num;
// 减去余粮
$wait_money-=$rand_num;
} else {
$value = $value+$wait_money;
break;
}
}
print_r($min_array);
echo array_sum($min_array);
}
function randMoney($min, $max){
$num = mt_rand($min, $max);
$point = $this->randFloat();
$point = floor($point * 100) / 100;
$money = $num + $point;
return $money;
}
function randFloat($min=0, $max=1){
return $min + mt_rand()/mt_getrandmax() * ($max-$min);
}
}
$obj = new redpackage();
return $obj->distribute(100,20,3,6);