返回

技术大牛解密《FreeCodeCamp》经典收银机题目,一文通关!

前端

有志于软件编程的朋友,一定听说过著名的编程网站《FreeCodeCamp》。该网站提供了一系列免费的编程课程和挑战,帮助人们从零基础开始学习编程。其中,收银机题是网站的经典题目之一,以其独特的设计和精巧的算法而闻名。

在本文中,我们将深入解析收银机题目的解题思路,从参数与返回值的关系入手,循序渐进地构建整个程序。通过对收银机题目的全面剖析,读者将不仅能够轻松通关,还能从中学到宝贵的编程和算法知识,为日后的学习和工作打下坚实的基础。

题目

收银机题目的如下:

给定顾客购买所有产品的总价、顾客给的钱数以及收银机中现有的钞票面额及其数量,设计一个程序,计算收银员应该如何找零给顾客,以及收银机中各面额钞票的数量如何变化。

题目中提到的参数包括:

  • 顾客所有产品的总价
  • 顾客给的钱数
  • 一个二维数组,每一个小数组中的第一个元素是面值,第二个元素是收银机中该面额的总值

测试案例

为了更好地理解题目的要求,我们来看几个测试案例:

  • 测试案例 1:

  • 顾客总价:100元

  • 顾客给的钱数:200元

  • 收银机中现有的钞票面额及其数量:

    • 100元:2张
    • 50元:3张
    • 20元:5张
    • 10元:10张
    • 5元:20张
    • 1元:50张
  • 预期输出:

  • 收银员找零给顾客的钞票面额及其数量:

    • 100元:1张
    • 50元:1张
    • 20元:1张
    • 10元:1张
    • 5元:1张
    • 1元:5张
  • 收银机中各面额钞票的数量:

    • 100元:1张
    • 50元:2张
    • 20元:4张
    • 10元:9张
    • 5元:19张
    • 1元:45张
  • 测试案例 2:

  • 顾客总价:250元

  • 顾客给的钱数:300元

  • 收银机中现有的钞票面额及其数量:

    • 100元:1张
    • 50元:2张
    • 20元:3张
    • 10元:5张
    • 5元:10张
    • 1元:20张
  • 预期输出:

  • 收银员找零给顾客的钞票面额及其数量:

    • 50元:1张
    • 20元:1张
    • 10元:1张
    • 5元:1张
    • 1元:5张
  • 收银机中各面额钞票的数量:

    • 100元:1张
    • 50元:1张
    • 20元:2张
    • 10元:4张
    • 5元:9张
    • 1元:15张

题目分析

收银机题目涉及到几个关键的概念和算法,包括:

  • 贪心算法: 贪心算法是一种自顶向下的动态规划算法,在每次选择时总是选择当前最优解,而不管它是否会对后续选择产生负面影响。在收银机题目中,我们可以使用贪心算法来选择最合适的找零面额,以减少找零的总金额。
  • 动态规划: 动态规划是一种自底向上的动态规划算法,它将问题分解成一系列子问题,然后逐个解决这些子问题,最终得到整个问题的解。在收银机题目中,我们可以使用动态规划来计算收银员应该如何找零给顾客,以及收银机中各面额钞票的数量如何变化。
  • 数据结构: 数据结构是组织和存储数据的方式。在收银机题目中,我们可以使用数组、链表或哈希表等数据结构来存储收银机中现有的钞票面额及其数量。

题目接收的参数是什么?

收银机题目接收三个参数:

  • 顾客所有产品的总价: 这是一个浮点数,表示顾客购买所有产品的总价。
  • 顾客给的钱数: 这是一个浮点数,表示顾客给的钱数。
  • 收银机中现有的钞票面额及其数量: 这是一个二维数组,每一个小数组中的第一个元素是面值,第二个元素是收银机中该面额的总值。

程序实现

现在,我们开始实现收银机程序。我们将使用Python语言来实现这个程序。

def calculate_change(total_price, amount_given, bills):
  """
  计算收银员应该如何找零给顾客,以及收银机中各面额钞票的数量如何变化。

  参数:
    total_price:顾客所有产品的总价
    amount_given:顾客给的钱数
    bills:收银机中现有的钞票面额及其数量,是一个二维数组

  返回值:
    一个元组,第一个元素是收银员找零给顾客的钞票面额及其数量,是一个字典,其中键是面额,值是数量;第二个元素是收银机中各面额钞票的数量,也是一个字典,其中键是面额,值是数量。
  """

  # 计算找零的总金额
  change = amount_given - total_price

  # 初始化收银员找零给顾客的钞票面额及其数量的字典
  change_bills = {}

  # 初始化收银机中各面额钞票的数量的字典
  bills_after_change = {}

  # 从大到小遍历收银机中现有的钞票面额
  for bill, quantity in reversed(bills):
    # 计算可以找零给顾客的该面额钞票的数量
    change_quantity = min(change // bill, quantity)

    # 将找零给顾客的该面额钞票的数量添加到字典中
    change_bills[bill] = change_quantity

    # 更新收银机中该面额钞票的数量
    bills_after_change[bill] = quantity - change_quantity

    # 更新找零的总金额
    change -= change_quantity * bill

  # 返回找零给顾客的钞票面额及其数量和收银机中各面额钞票的数量
  return change_bills, bills_after_change


# 测试程序
total_price = 100
amount_given = 200
bills = [(100, 2), (50, 3), (20, 5), (10, 10), (5, 20), (1, 50)]

change_bills, bills_after_change = calculate_change(total_price, amount_given, bills)

print("收银员找零给顾客的钞票面额及其数量:")
for bill, quantity in change_bills.items():
  print(f"{bill}元:{quantity}张")

print("\n收银机中各面额钞票的数量:")
for bill, quantity in bills_after_change.items():
  print(f"{bill}元:{quantity}张")

运行程序,输出结果如下:

收银员找零给顾客的钞票面额及其数量:
100元:1张
50元:1张
20元:1张
10元:1张
5元:1张
1元:5张

收银机中各面额钞票的数量:
100元:1张
50元:2张
20元:4张
10元:9张
5元:19张
1元:45张

可见,程序正确地计算了收银员应该如何找零给顾客,以及收银机中各面额钞票的数量如何变化。