持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
题目描述
小扣在秋日市集选择了一家早餐摊位,一维整型数组 staple 中记录了每种主食的价格,一维整型数组 drinks 中记录了每种饮料的价格。小扣的计划选择一份主食和一款饮料,且花费不超过 x 元。请返回小扣共有多少种购买方案。
注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1
示例 1:
输入:staple = [10,20,5], drinks = [5,5,2], x = 15
输出:6
解释:小扣有 6 种购买方案,所选主食与所选饮料在数组中对应的下标分别是: 第 1 种方案:staple[0] + drinks[0] = 10 + 5 = 15; 第 2 种方案:staple[0] + drinks[1] = 10 + 5 = 15; 第 3 种方案:staple[0] + drinks[2] = 10 + 2 = 12; 第 4 种方案:staple[2] + drinks[0] = 5 + 5 = 10; 第 5 种方案:staple[2] + drinks[1] = 5 + 5 = 10; 第 6 种方案:staple[2] + drinks[2] = 5 + 2 = 7。
二分
这个题目我的初步思路是:一开始我的想法是直接套个双重循环模拟做,但是果然给我吃了TE,后面发现其实可以二分,并且把两层换成一层,进行空间置换成时间的操作,即使用一个数组drinkCount,数组下标i表示饮料价格,drinkCount[i] 表示小于等于价格i的饮料个数。于是遍历staple,将用来购买饮料的价格cha计算出来,于是在1<= i <= 100000 范围内drinkCount[cha]就是该主餐下能购买饮料的个数。只要先处理一遍staple数组,使得arr[i]中存放的数的含义是小于等于i元的选择在staple数组中共有多少个。然后遍历drinks数组,针对每个元素(假如选了这个的话)都可以从arr数组中常数时间查询到对应的组合有多种。具体实现如下:
- 首先我们将两个数组进行排序,并且定义好统计变量res。
- 然后去定义快慢指针,一个从staple数组的0索引位置,另一个从drinks.length-1位置开始。
- 遍历的过程去判断当两个数组的指针都没走到极限位置,例如,staple指针往后走,drinks指针往前走,这是判断的条件。
- 判断i和j指针对应的值是不是小于等于x,如果小于,res更新,只要是j指针位置满足的,那么j指针前面的索引位置的数必然满足,所以是res+j+1,并且要取模,防止数据溢出。
- 不断推进,即i指针前移,j指针后移。
class Solution {
public int breakfastNumber(int[] staple, int[] drinks, int x) {
Arrays.sort(staple);
Arrays.sort(drinks);
int mod = 1000000007;
int n = staple.length;
int m = drinks.length - 1;
int i = 0, j = m, res = 0;
while(i < n && j >= 0) {
if(staple[i] + drinks[j] <= x) {
res = (res + j + 1) % mod;
i++;
} else {
j--;
}
}
return res % mod;
}
}
最后
注意:看清题目!!看清题目!!看清题目!!,注意取模,血泪的教训。