LeetCode破解之早餐搭配

138 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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;
    }
}

最后

注意:看清题目!!看清题目!!看清题目!!,注意取模,血泪的教训。