这道题目反映了日常生活中常见的一种情景。我们的目标是为每一位顾客提供找零服务。如果能确保每位顾客都能得到足够的找零,那么我们返回 `true`;反之,如果任何一位顾客无法得到足够的找零,我们则返回 `false`。
顾客使用的纸币仅限于5元、10元和20元三种。我们需要关注的是5元和10元的纸币数量,因为20元纸币无法用于找零。
具体操作如下:
当顾客支付5元时,我们将5元纸币的数量增加1。
当顾客支付10元时,我们需要找给他一张5元纸币,因此5元纸币的数量减少1。在此之后,我们检查5元纸币的数量,如果数量变为负数,表明我们无法完成找零,此时应立即返回 `false`。
当顾客支付20元时,根据常规做法,我们应优先使用10元纸币进行找零,然后再使用一张5元纸币。如果没有10元纸币,我们则使用三张5元纸币进行找零。完成找零后,我们同样需要检查5元纸币的数量,如果数量小于0,则表明找零失败,应返回 `false`。
下面的代码实现了一个贪心算法。贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。
在这个问题中,代码遵循了以下贪心策略:
优先使用10元找零:当顾客支付20元时,如果有10元的零钱,优先使用10元找零,然后再使用5元找零。这是因为10元纸币在找零时比5元纸币更“珍贵”,因为它可以一次性找零10元,而5元纸币需要两张才能达到同样的效果。
尽量保留5元纸币:5元纸币是最基本的找零单位,因此在找零时尽量保留5元纸币,以备后续可能需要用更多的5元纸币找零的情况。
代码通过遍历顾客支付的账单数组,根据每一步的支付金额来更新店员手中的5元和10元纸币的数量,并在每一步检查5元纸币的数量是否足够找零。如果某一步5元纸币的数量变为负数,说明无法完成找零,算法返回false
。如果遍历结束时5元纸币的数量始终非负,则说明可以完成所有找零,算法返回true
。
这种策略确保了在每一步都做出了当前看起来最优的选择,即使用了贪心算法的思想。
#include
#include
bool lemonadeChange(std::vector& bills) {
int five = 0, ten = 0;
for (int bill : bills) {
if (bill == 5) {
five++;
} else if (bill == 10) {
if (five == 0) return false;
five--;
ten++;
} else { // bill == 20
if (ten > 0 && five > 0) {
ten--;
five--;
} else if (five >= 3) {
five -= 3;
} else {
return false;
}
}
}
return true;
}
int main() {
std::vector bills = {5, 5, 5, 10, 20};
if (lemonadeChange(bills)) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
return 0;
}
在进行找零操作时,我们并未事先检查5元纸币的数量,而是在完成找零后才评估5元纸币的余量是充足还是不足。当然,我们也可以在每次找零前预先判断5元纸币的数量,但这会略显繁琐,因为除了顾客支付5元的情况外,其他情况下都需要进行这一额外的检查步骤。