leetcode
leetcode 2901 ~ 2950
早餐组合

早餐组合

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 149 ms, 内存: 31.0 MB


/*
 * 思路:
 * 1. 对主食数组 staple 进行排序。
 * 2. 使用流操作遍历饮料数组 drinks,对于每一个饮料价格,使用二分查找在主食数组中找到可以搭配的最大主食价格。
 * 3. 计算满足条件的主食数量并累加到总数中。
 * 4. 最后对结果取模 1e9 + 7。
 */
import java.util.Arrays;
import java.util.stream.IntStream;

public class BreakfastComboStream {
    public int breakfastNumber(int[] staple, int[] drinks, int x) {
        Arrays.sort(staple);
        int MOD = 1000000007;
        return IntStream.of(drinks).map(drink -> {
            int maxStaple = x - drink;
            if (maxStaple <= 0) return 0;
            int left = 0, right = staple.length - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (staple[mid] <= maxStaple) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return left;
        }).reduce(0, (a, b) -> (a + b) % MOD);
    }
}

解释

方法:

这个题解采用了前缀和的思想加上一点优化来减少查找时间。首先,创建一个长度为x+1的数组arr,用于记录每个价格以下的主食数量。遍历主食数组staple,对于每个价格小于x的主食,增加arr中对应价格索引的计数。然后,对arr数组进行前缀和处理,使得arr[i]表示所有价格小于等于i的主食总数。接着,遍历饮料数组drinks,对每种饮料,计算其与主食组合的最大可接受价格x-drink。如果这个值大于0,那么直接从arr数组中得到所有价格小于等于这个值的主食数量,加到答案中。最后,由于可能出现计数非常大的情况,对最终结果取模1e9+7。

时间复杂度:

O(n + m + x)

空间复杂度:

O(x)

代码细节讲解

🦆
为什么在计算前缀和时,数组arr的起始索引是从2开始,而不是从1开始?
在计算前缀和时,起始索引从2开始是由于算法中的逻辑错误或者是代码实现上的疏忽。正确的实现应该是从索引1开始计算前缀和,因为索引1代表价格为1的主食数量,这也意味着需要累加从价格1开始的所有主食数量。从2开始会导致忽略了价格为1的主食数量在前缀和中的累加,这是不正确的。应该从1开始,确保所有有效价格的主食都被正确计算在内。
🦆
在处理饮料数组时,如果lt(x-drink)的值小于等于0,这种情况是如何处理的,它会对总方案数产生什么影响?
当lt(x-drink)的值小于等于0时,这意味着饮料的价格已经超过了组合的预算上限x。在代码中这种情况会被直接跳过(continue语句),因此不会对总方案数产生任何贡献。这是一种有效的处理方法,因为任何超出预算的饮料都不能与任何主食形成有效的价格组合,所以这些情况应当被排除在外。
🦆
在实现中,对于超过x的主食价格,没有进行任何操作,这是否意味着价格超过x的主食在方案中完全不被考虑?这种处理是否合理?
是的,在实现中如果主食的价格超过了x,那么这个主食价格不会被记录在arr数组中,意味着它不会被考虑在内。这种处理是合理的,因为如果主食的价格本身已经超出了整体预算x,那么无论如何搭配饮料,这种组合的总价格都会超出x,不可能成为一个有效的选项。因此,忽略这些超出预算的主食是正确和必要的。

相关问题