zoukankan      html  css  js  c++  java
  • [LeetCode] 638. Shopping Offers

    In LeetCode Store, there are n items to sell. Each item has a price. However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.

    You are given an integer array price where price[i] is the price of the ith item, and an integer array needs where needs[i] is the number of pieces of the ith item you want to buy.

    You are also given an array special where special[i] is of size n + 1 where special[i][j] is the number of pieces of the jth item in the ith offer and special[i][n] (i.e., the last integer in the array) is the price of the ith offer.

    Return the lowest price you have to pay for exactly certain items as given, where you could make optimal use of the special offers. You are not allowed to buy more items than you want, even if that would lower the overall price. You could use any of the special offers as many times as you want.

    Example 1:

    Input: price = [2,5], special = [[3,0,5],[1,2,10]], needs = [3,2]
    Output: 14
    Explanation: There are two kinds of items, A and B. Their prices are $2 and $5 respectively. 
    In special offer 1, you can pay $5 for 3A and 0B
    In special offer 2, you can pay $10 for 1A and 2B. 
    You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.
    

    Example 2:

    Input: price = [2,3,4], special = [[1,1,0,4],[2,2,1,9]], needs = [1,2,1]
    Output: 11
    Explanation: The price of A is $2, and $3 for B, $4 for C. 
    You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C. 
    You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C. 
    You cannot add more items, though only $9 for 2A ,2B and 1C.

    Constraints:

    • n == price.length
    • n == needs.length
    • 1 <= n <= 6
    • 0 <= price[i] <= 10
    • 0 <= needs[i] <= 10
    • 1 <= special.length <= 100
    • special[i].length == n + 1
    • 0 <= special[i][j] <= 50

    大礼包。

    在 LeetCode 商店中, 有 n 件在售的物品。每件物品都有对应的价格。然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。

    给你一个整数数组 price 表示物品价格,其中 price[i] 是第 i 件物品的价格。另有一个整数数组 needs 表示购物清单,其中 needs[i] 是需要购买第 i 件物品的数量。

    还有一个数组 special 表示大礼包,special[i] 的长度为 n + 1 ,其中 special[i][j] 表示第 i 个大礼包中内含第 j 件物品的数量,且 special[i][n] (也就是数组中的最后一个整数)为第 i 个大礼包的价格。

    返回 确切 满足购物清单所需花费的最低价格,你可以充分利用大礼包的优惠活动。你不能购买超出购物清单指定数量的物品,即使那样会降低整体价格。任意大礼包可无限次购买。

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

    思路是 backtracking。我们需要买一些商品,每件商品的个数我们用一个 list 记录好了。我们也有一些 offer,会有一些特别的价钱。我们的目的是看看能否买到所有的东西并且使得总价最低。注意这里不能为了得到更优惠的价钱而多买任何东西。

    使用 backtracking 是因为我们不知道走到哪一步,就不能再使用某个 offer 了。当我们不能使用某个 offer 的时候,我们要往回退一步接着试探别的 offer。这里的 base case 是所有需要的东西都按原来的单价购买。

    时间O(n)

    空间O(n)

    Java实现

     1 class Solution {
     2     int minPrice;
     3     
     4     private int directBuy(List<Integer> price, List<Integer> needs) {
     5         int sum = 0;
     6         int n = price.size();
     7         for (int i = 0; i < n; i++) {
     8             sum += price.get(i) * needs.get(i);
     9         }
    10         return sum;
    11     }
    12 
    13     public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) {
    14         minPrice = directBuy(price, needs);
    15         helper(price, special, needs, 0, 0);
    16         return minPrice;
    17     }
    18 
    19     // 检查是否能使用当前的special price
    20     private boolean canUse(List<Integer> offer, List<Integer> needs) {
    21         int n = needs.size();
    22         for (int i = 0; i < n; i++) {
    23             if (needs.get(i) < offer.get(i)) {
    24                 return false;
    25             }
    26         }
    27         return true;
    28     }
    29 
    30     private void helper(List<Integer> price, List<List<Integer>> special, List<Integer> needs, int index, int used) {
    31         // base case
    32         if (used >= minPrice) {
    33             return;
    34         }
    35 
    36         // 如果遍历完special price之后还没有买完需要的东西,则按原来的单价购买
    37         if (index == special.size()) {
    38             used += directBuy(price, needs);
    39             // 如果购买价可以被更新则更新
    40             if (used < minPrice) {
    41                 minPrice = used;
    42             }
    43             return;
    44         }
    45 
    46         List<Integer> offer = special.get(index);
    47         if (canUse(offer, needs)) {
    48             int n = needs.size();
    49             List<Integer> updatedNeeds = new ArrayList<>();
    50             for (int i = 0; i < n; i++) {
    51                 updatedNeeds.add(needs.get(i) - offer.get(i));
    52             }
    53             helper(price, special, updatedNeeds, index, used + offer.get(n));
    54         }
    55         helper(price, special, needs, index + 1, used);
    56     }
    57 }

    LeetCode 题目总结

  • 相关阅读:
    JavaScript原型、闭包、继承和原型链等等总结
    JS创建对象的几种方式整理
    js中 给json对象添加属性和json数组添加元素
    JSON 数组
    httpclient封装
    java 数字和日期处理
    jmeter所有版本下载路径
    idea的使用
    Java环境的搭建
    Axure8.0可用的授权码
  • 原文地址:https://www.cnblogs.com/cnoodle/p/15473589.html
Copyright © 2011-2022 走看看