关于任意金额分配10元、5元、2元的算法

今天去一家做电商的公司面试,笔试题有个算法,如下:

输入任意金额,计算分配出10元、5元、2元是否可以分配,如果可以分别分配几张。

根据需求可知优先分配最高金额,根据最高金额计算出分配值,然后取整数。再用输入金额减去最高金额计算出的整数乘以最高金额,得出余额。一开始我想的是分别计算,嵌套多层if else后来发现不是很友好,还越来越乱。再加上是在a4纸上手写代码,很烦躁。

晚上回家花了半个小时思索,写了这样的。

function findMoney($money = 0)
{
    $no_text = "不能找回金额为" . $money . "的零钱。";
    $text = "可以找回金额为" . $money . "的零钱,其中";
    if ($money <= 0) {
        echo $no_text;
    }
    $rand = [10, 5, 2];
    for ($i = 0; $i < count($rand); $i++) {
        if ($rand[$i] > 0) {
            $number = floor($money / $rand[$i]);
            $money = $money - $number * $rand[$i];
            $text .= "面额" . $rand[$i] . "元的" . $number . "张" . ",";
            if ($money == 1) {
                echo $no_text . PHP_EOL;
                exit;
            }
        }
    }
    echo $text . PHP_EOL;
}
findMoney(16);

今天周二,昨晚弄得比较晚,急着睡。下午又想了想感觉不对。
输入6或者8的时候并不能分配。
对昨天的代码优化一番。

如下

function findMoney($money = 0)
{
    $no_text = "不能找回金额为" . $money . "的零钱。";
    $text = "可以找回金额为" . $money . "的零钱,其中";
    if ($money <= 0) {
        echo $no_text;
    }
    $rand = [10, 5, 2];
    for ($i = 0; $i < count($rand); $i++) {
        if ($rand[$i] > 0) {
            $number = floor($money / $rand[$i]);
            $money = $money - $number * $rand[$i];
            $text .= "面额" . $rand[$i] . "元的" . $number . "张" . ",";
            if ($money == 1) {
                echo $no_text . PHP_EOL;
                exit;
            }
        }
    }
    echo $text . PHP_EOL;
}
findMoney(16);

后续改进

如下

function findMoney($money = 0)
{
    //print_r($money);exit;
    $no_text = "不能找回金额为" . $money . "的零钱。";
    $text = "可以找回金额为" . $money . "的零钱,其中";
    if ($money <= 0) {
        echo $no_text;
    }
    $rand = [10, 5, 2];
    $number = 0;
    for ($i = 0; $i < count($rand); $i++) {
        if (isset($rand[$i])) {
            //不能整除的情况
            if (is_float($money / $rand[$i])) {
                $number = $money / $rand[$i];
                if ($money > 0 && $rand[$i] == 5 && ceil($number) != $number) {
                    $text .= "面额" . $rand[$i] . "元的0张" . ",";
                    $text .= getChildMoney($money);
                }else{
                    $number = is_float($number) == 1 ? floor($number) : $number;
                    $money = $money - $number * $rand[$i];
                    $text .= "面额" . $rand[$i] . "元的" . $number . "张" . ",";
                }
            } else {
                $number = $money / $rand[$i];
                $money = $money - $number * $rand[$i];
                $text .= "面额" . $rand[$i] . "元的" . $number . "张" . ",";
                if ($money == 0) {
                    continue;
                }
            }
        }
    }
    if ($money > 0) {
        echo $no_text . PHP_EOL;
    } else {
        echo $text . PHP_EOL;
    }
}

function getChildMoney($money = 0)
{
    $number = $money / 2;
    if (is_float($number)) {
        return false;
    }
    $text = "面额" . $money . "元的" . $number . "张" . ",";
    return $text;
}

findMoney(34);

这样就是任意金额