记一次面试-简单的微信红包分配算法

本文介绍了一种将固定金额的红包平均分配到多个用户手中的算法。该算法确保了每个人获得的红包金额不低于设定的最小值,并且总额保持不变。通过实例演示了如何使用PHP实现这一算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记一次面试-简单的红包分配算法

简介

是这个样子的,前段时间去面试,接近尾声时面试官突然提出这样一个问题:将一个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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值