LCP 18.早餐组合

小扣在秋日市集选择了一家早餐摊位,一维整型数组 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。

示例 2:

输入:staple = [2,1,1], drinks = [8,9,5,1], x = 9
输出:8
解释:小扣有 8 种购买方案,所选主食与所选饮料在数组中对应的下标分别是:
第 1 种方案:staple[0] + drinks[2] = 2 + 5 = 7;
第 2 种方案:staple[0] + drinks[3] = 2 + 1 = 3;
第 3 种方案:staple[1] + drinks[0] = 1 + 8 = 9;
第 4 种方案:staple[1] + drinks[2] = 1 + 5 = 6;
第 5 种方案:staple[1] + drinks[3] = 1 + 1 = 2;
第 6 种方案:staple[2] + drinks[0] = 1 + 8 = 9;
第 7 种方案:staple[2] + drinks[2] = 1 + 5 = 6;
第 8 种方案:staple[2] + drinks[3] = 1 + 1 = 2;

提示:
1 <= staple.length <= 10^5
1 <= drinks.length <= 10^5
1 <= staple[i],drinks[i] <= 10^5
1 <= x <= 2*10^5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/2vYnGI
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1.最基本的思路:暴力求解

通过依次排列组合,这样的解法会超时,测试例库中有非常变态的测试用例

[1,1,1,1,1,1,1,1,1,1,1,1,1…]
[1,1,1,1,1,1,1,1,1,1,1,1,1…]
2

//排列组合
int breakfastNumber(int* staple, int stapleSize, int* drinks, int drinksSize, int x){
    int i;
    int j;
    int count=0;
    for(i = 0; i < stapleSize; i++){
        for(j = 0; j < drinksSize; j++){
            if(staple[i]+drinks[j]  <= x){
                count = count % 1000000007;
                count++;
            }
        }
    }
    return count;
}

2.优化

  1. 调用C库函数qsort(),先排序
  2. 进一步排列组合,减少组合次数,发现也超时
 # define yichu 1000000007;
int compar(const void *p1,const void*p2){
    const int * a1 = (const int *) p1;
    const int * a2 = (const int *) p2;
    if (*a1 < *a2)
        return -1;
    else if (*a1 == *a2)
        return 0;
    else
        return 1;
}

int breakfastNumber(int* staple, int stapleSize, int* drinks, int drinksSize, int x){
    int i;
    int j;
    int k = drinksSize-1;
    int count=0;
    qsort(staple,stapleSize,sizeof(int),compar);//默认升序
    qsort(drinks,drinksSize,sizeof(int),compar);//默认升序
    for(i =0; i < stapleSize ; i++){
        for(j = k; j >= 0;j--){
            if(staple[i]+drinks[j]  <= x){
                count = (count+(j+1)) % yichu;
                k = j;//记录遍历的位置
                break;
            }
        }
    }
    return count;
}

3.终极解法

#define mod 1000000007
int breakfastNumber(int* staple, int stapleSize, int* drinks, int drinksSize, int x){
    int cnt[100001] = {0};
    //类似哈希表,将数组元素的值写入新的数组,下标值即对应元素值
    for (int i=0; i<drinksSize; ++i) 
        cnt[drinks[i]] += 1;
     
    //计算数组中的每个下标前的元素个数。也就是某个计算饮料数组中小于等于此处下标值得元素个数
    for (int i=1; i<100001; ++i)
        cnt[i] += cnt[i-1];
    long num = 0;
    for (int i=0; i<stapleSize; ++i) {
        int idx = x - staple[i];
        //查看下标处的值(个数)
        if (idx >= 0) {
            idx = fmin(idx, 100000);//调用函数fmin(),当idx超过100000时,说明都符合要求,所以取数组下标为100000的值
            num += cnt[idx];
            if (num >= mod) num %= mod;
        }
    }
    return num;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值