购买两块巧克力

标签: 数组 排序

难度: Easy

给你一个整数数组 prices ,它表示一个商店里若干巧克力的价格。同时给你一个整数 money ,表示你一开始拥有的钱数。

你必须购买 恰好 两块巧克力,而且剩余的钱数必须是 非负数 。同时你想最小化购买两块巧克力的总花费。

请你返回在购买两块巧克力后,最多能剩下多少钱。如果购买任意两块巧克力都超过了你拥有的钱,请你返回 money 。注意剩余钱数必须是非负数。

示例 1:

输入:prices = [1,2,2], money = 3
输出:0
解释:分别购买价格为 1 和 2 的巧克力。你剩下 3 - 3 = 0 块钱。所以我们返回 0 。

示例 2:

输入:prices = [3,2,3], money = 3
输出:3
解释:购买任意 2 块巧克力都会超过你拥有的钱数,所以我们返回 3 。

提示:

  • 2 <= prices.length <= 50
  • 1 <= prices[i] <= 100
  • 1 <= money <= 100

Submission

运行时间: 16 ms

内存: 16.5 MB

class Solution:
    def buyChoco(self, prices: List[int], money: int) -> int:
        prices.sort()
        if money < prices[0] + prices[1]:
            return money
        else:
            return money - prices[0] - prices[1]

Explain

题目要求购买两块巧克力并最小化总花费以使得剩余的钱最多。首先,我们对价格数组进行排序。如果有足够的钱购买最便宜的两块巧克力(即排序后的前两个价格),则购买这两块巧克力,并计算剩余的钱。如果连最便宜的两块巧克力都买不起,则直接返回持有的钱数。

时间复杂度: O(n log n)

空间复杂度: O(1)

# 定义解决方案类
class Solution:
    def buyChoco(self, prices: List[int], money: int) -> int:
        # 对价格数组进行排序
        prices.sort()
        # 检查最便宜的两块巧克力的价格之和是否超过持有的钱
        if money < prices[0] + prices[1]:
            # 如果超过,直接返回持有的钱数
            return money
        else:
            # 否则,购买这两块巧克力并返回剩余的钱
            return money - prices[0] - prices[1]

Explore

对价格数组进行排序是为了快速而直接地找到最低的两个价格,从而确保购买这两块巧克力后剩余的钱最多。虽然排序操作的时间复杂度为O(n log n),这可能不是在所有情况下最优的方法(例如使用线性时间的选择算法找到最小的两个数),但它简化了逻辑并保证了解决方案的正确性和直观性。对于小到中等规模的数据,这种方法是有效且实用的。

是的,在排序后直接选择最便宜的两块巧克力确实保证剩余金钱最多。这是因为任何其他两块巧克力的组合的成本将会等于或大于最便宜的两块的成本。数学上,如果a <= b <= c,那么a + b一定是a、b、c三者中任意两数相加的最小可能值。因此,不存在其他选择会使剩余的金钱更多的情况。

在现实中,如果预先知道连两块最便宜的巧克力都买不起,确实没有必要进行排序操作,因为排序本身有一定的计算成本。然而,在不了解具体价格分布的情况下,排序是一种保证找到最低价格并正确判断是否能购买的简单方法。一个更高效的实现可能包括先检查价格数组中的最小值,如果单个最低价格都超过了拥有的钱,则无需进行进一步的操作。

是的,题解中的方法通过排序确保了即使存在多个相同的最低价格,也能正确处理。排序后的数组会将所有相同的最低价格放置在前面,因此直接选择前两个价格是有效的。这确保了算法在面对任何价格分布时都能正常工作。