“小U的早餐选择问题”题目要求
一、问题描述
小U同学每天在早餐店有多种主食和饮料可以选择。给定两个数组,staples 表示不同主食的价格,drinks 表示不同饮料的价格。每天早上,小U最多会花费不超过 xx 元,他可能选择一份主食、一杯饮料,或只选择主食或饮料中的一个。你的任务是计算小U每天早上有多少种不同的选择,满足其最大花费不超过 xx。
例如:对于输入的主食价格 5 20 5 和饮料价格 5 5 2,如果小U的最大花费为 5,则一共有 5 种不同的选择。
二、测试样例
样例1:
输入:
staples = [5, 20, 5] ,drinks = [5, 5, 2] ,x = 5
输出:5
样例2:
输入:
staples = [3, 10, 7] ,drinks = [2, 5] ,x = 7
输出:5
样例3:
输入:
staples = [10, 15] ,drinks = [5, 6] ,x = 20
输出:7
三、题目解析
3.1代码思路
问题的主要任务是:
-
计算两类商品(主食和饮料)的价格组合在指定预算内的所有可能性。
-
包括以下三种组合情况:
- 只选择主食的组合。
- 只选择饮料的组合。
- 同时选择主食和饮料的组合。
通过暴力遍历的方式实现,逐一检查各类商品价格是否满足预算条件。
- 统计只选择主食的情况:遍历
staples数组,统计价格不超过x的主食数量。 - 统计只选择饮料的情况:遍历
drinks数组,统计价格不超过x的饮料数量。 - 统计主食和饮料组合的情况:双重循环遍历
staples和drinks数组,统计主食和饮料的总价格不超过x的组合数量。 - 总的选择数:将上述三种情况的数量相加。
3.2详细代码
import java.util.Arrays;
public class Main {
public static int solution(int[] staples, int[] drinks, int x) {
// 统计只选择主食的情况
int countStaples = 0;
for (int price : staples) {
if (price <= x) {
countStaples++;
}
}
// 统计只选择饮料的情况
int countDrinks = 0;
for (int price : drinks) {
if (price <= x) {
countDrinks++;
}
}
// 统计主食和饮料组合的情况
int countCombination = 0;
for (int staplePrice : staples) {
for (int drinkPrice : drinks) {
if (staplePrice + drinkPrice <= x) {
countCombination++;
}
}
}
// 总的选择数 = 只选择主食 + 只选择饮料 + 主食和饮料组合
return countStaples + countDrinks + countCombination;
}
public static void main(String[] args) {
System.out.println(solution(new int[]{5, 20, 5}, new int[]{5, 5, 2}, 5) == 5);
System.out.println(solution(new int[]{3, 10, 7}, new int[]{2, 5}, 7) == 5);
System.out.println(solution(new int[]{10, 15}, new int[]{5, 6}, 20) == 7);
}
}
四、知识总结
虽然暴力遍历实现简单,但并非高效。我们可以通过使用排序和双指针技术优化组合计算,将主食和饮料数组按升序排序后,通过双指针避免多余的遍历操作:
- 固定主食价格,尝试找到满足条件的饮料组合数。
- 通过逐步调整指针,减少不必要的重复计算。
五、性能分析
1. 时间复杂度
- 统计单一商品的时间复杂度为 O(n)和 O(m),其中 nnn 和 m分别为主食和饮料数组的长度。
- 计算商品组合的时间复杂度为 O(n×m),因其使用了双重嵌套循环。
- 总体时间复杂度为 O(n+m+n×m),当数组规模较大时,组合计算部分可能成为性能瓶颈。
2. 空间复杂度
代码中未使用额外的数据结构,空间复杂度为 O(1)。