小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

C++解题

问题理解

小U每天早上可以选择一份主食、一杯饮料,或者只选择主食或饮料中的一个。我们需要计算在不超过给定预算 x 的情况下,有多少种不同的选择。

数据结构选择

  • staples 和 drinks 是两个数组,分别表示主食和饮料的价格。
  • 我们需要遍历这两个数组,计算所有可能的组合,并统计满足条件的组合数量。

算法步骤

  1. 遍历主食数组:对于每一个主食价格,检查它是否小于等于 x,如果是,则计数加一。
  2. 遍历饮料数组:对于每一个饮料价格,检查它是否小于等于 x,如果是,则计数加一。
  3. 组合选择:对于每一个主食价格,遍历饮料数组,计算主食和饮料的总价格,如果总价格小于等于 x,则计数加一。

关键点

  • 需要避免重复计数,即只计算有效的组合。
  • 可以使用两个嵌套循环来实现主食和饮料的组合遍历。

代码实现

#include <iostream>
#include <vector>

int solution(const std::vector<int>& staples, const std::vector<int>& drinks, int x) {
    // PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    // write code here
    int count = 0;

    // 遍历主食数组,统计单个主食价格小于等于 x 的情况
    for (int staple : staples) {
        if (staple <= x) {
            count++;
        }
    }

    // 遍历饮料数组,统计单个饮料价格小于等于 x 的情况
    for (int drink : drinks) {
        if (drink <= x) {
            count++;
        }
    }

    // 遍历主食和饮料数组,统计主食和饮料组合价格小于等于 x 的情况
    for (int staple : staples) {
        for (int drink : drinks) {
            if (staple + drink <= x) {
                count++;
            }
        }
    }

    return count;
}

int main() {
    std::cout << (solution({5, 20, 5}, {5, 5, 2}, 5) == 5) << std::endl;
    std::cout << (solution({3, 10, 7}, {2, 5}, 7) == 5) << std::endl;
    std::cout << (solution({10, 15}, {5, 6}, 20) == 7) << std::endl;
    return 0;
}

Python解题

思路说明

题目要求计算小U在早餐店有多少种不同的选择,使得其花费不超过给定的最大金额 x。我们可以通过以下步骤来解决这个问题:

  1. 首先,对主食和饮料的价格进行排序,这样可以利用二分查找快速找到满足条件的组合。
  2. 计算只选择主食或只选择饮料的情况,即价格不超过 x 的主食和饮料的数量。
  3. 计算选择一份主食和一杯饮料的组合情况,通过遍历主食价格,利用二分查找找到与之搭配的饮料价格,使得总价格不超过 x。

解题过程

  1. 排序:对主食和饮料的价格数组进行排序,以便后续使用二分查找。
  2. 计算单选情况:使用 bisect_right 函数分别计算主食和饮料中价格不超过 x 的数量,并将其相加。
  3. 计算组合情况:遍历每个主食价格 k,对于每个 k,使用 bisect_right 函数找到饮料中价格不超过 x−k 的数量,并将其累加到结果中。

复杂度分析

  • 时间复杂度:排序的时间复杂度为 O(nlogn),其中 n 是主食或饮料的数量。二分查找的时间复杂度为 O(logn),遍历主食的时间复杂度为 O(n)。因此,总的时间复杂度为 O(nlogn)。
  • 空间复杂度:排序需要额外的空间来存储排序后的数组,空间复杂度为 O(n)。

知识点扩展

  • 排序算法:排序是解决许多问题的基本工具,常见的排序算法有快速排序、归并排序等。
  • 二分查找:二分查找是一种高效的查找算法,适用于已排序的数组,可以在 O(logn) 的时间复杂度内找到目标值。
  • 组合优化:这类问题通常涉及在给定约束下找到所有可能的组合,可以通过遍历和剪枝等方法来解决。

代码实现

def solution(staples: list, drinks: list, x: int) -> int:
    from bisect import bisect_right
    a = sorted(staples)
    b = sorted(drinks)
    ans = bisect_right(a, x) + bisect_right(b, x)
    for k in a:
        ans += bisect_right(b, x - k)
    return ans


if __name__ == '__main__':
    print(solution(staples = [5, 20, 5] ,drinks = [5, 5, 2] ,x = 5) == 5)
    print(solution(staples = [3, 10, 7] ,drinks = [2, 5] ,x = 7) == 5)
    print(solution(staples = [10, 15] ,drinks = [5, 6] ,x = 20) == 7)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值