leetcode
leetcode 2301 ~ 2350
购买两块巧克力

购买两块巧克力

难度:

标签:

题目描述

You are given an integer array prices representing the prices of various chocolates in a store. You are also given a single integer money, which represents your initial amount of money.

You must buy exactly two chocolates in such a way that you still have some non-negative leftover money. You would like to minimize the sum of the prices of the two chocolates you buy.

Return the amount of money you will have leftover after buying the two chocolates. If there is no way for you to buy two chocolates without ending up in debt, return money. Note that the leftover must be non-negative.

 

Example 1:

Input: prices = [1,2,2], money = 3
Output: 0
Explanation: Purchase the chocolates priced at 1 and 2 units respectively. You will have 3 - 3 = 0 units of money afterwards. Thus, we return 0.

Example 2:

Input: prices = [3,2,3], money = 3
Output: 3
Explanation: You cannot buy 2 chocolates without going in debt, so we return 3.

 

Constraints:

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

代码结果

运行时间: 16 ms, 内存: 16.5 MB


/*
 * 题目思路:
 * 使用Java Stream API处理这个问题,我们可以先生成所有可能的巧克力组合的总价。 
 * 然后过滤出总价小于等于money的组合,最后找出能剩下的最多钱数。 
 */
import java.util.*;
import java.util.stream.*;

public class ChocolateShoppingStream {
    public static int maxMoneyLeft(int[] prices, int money) {
        int maxRemaining = Arrays.stream(prices)
                                  .boxed()
                                  .flatMap(i -> Arrays.stream(prices).boxed().map(j -> i + j))
                                  .filter(total -> total <= money)
                                  .map(total -> money - total)
                                  .max(Integer::compareTo)
                                  .orElse(money);
        return maxRemaining;
    }

    public static void main(String[] args) {
        int[] prices1 = {1, 2, 2};
        int money1 = 3;
        System.out.println(maxMoneyLeft(prices1, money1)); // 输出:0

        int[] prices2 = {3, 2, 3};
        int money2 = 3;
        System.out.println(maxMoneyLeft(prices2, money2)); // 输出:3
    }
}

解释

方法:

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

时间复杂度:

O(n log n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么选择对价格数组进行排序,而不是使用其他可能更高效的方法?
对价格数组进行排序是为了快速而直接地找到最低的两个价格,从而确保购买这两块巧克力后剩余的钱最多。虽然排序操作的时间复杂度为O(n log n),这可能不是在所有情况下最优的方法(例如使用线性时间的选择算法找到最小的两个数),但它简化了逻辑并保证了解决方案的正确性和直观性。对于小到中等规模的数据,这种方法是有效且实用的。
🦆
在排序后直接选择最便宜的两块巧克力是否总是保证剩余金钱最多?是否存在选择其他两块巧克力但剩余更多金钱的情况?
是的,在排序后直接选择最便宜的两块巧克力确实保证剩余金钱最多。这是因为任何其他两块巧克力的组合的成本将会等于或大于最便宜的两块的成本。数学上,如果a <= b <= c,那么a + b一定是a、b、c三者中任意两数相加的最小可能值。因此,不存在其他选择会使剩余的金钱更多的情况。
🦆
题解中提到如果连最便宜的两块巧克力都买不起则返回持有的钱数,这种情况下是否还有必要进行排序操作?
在现实中,如果预先知道连两块最便宜的巧克力都买不起,确实没有必要进行排序操作,因为排序本身有一定的计算成本。然而,在不了解具体价格分布的情况下,排序是一种保证找到最低价格并正确判断是否能购买的简单方法。一个更高效的实现可能包括先检查价格数组中的最小值,如果单个最低价格都超过了拥有的钱,则无需进行进一步的操作。
🦆
如果价格数组中存在多个相同的最低价格,题解中的方法是否考虑了这一点?
是的,题解中的方法通过排序确保了即使存在多个相同的最低价格,也能正确处理。排序后的数组会将所有相同的最低价格放置在前面,因此直接选择前两个价格是有效的。这确保了算法在面对任何价格分布时都能正常工作。

相关问题