leetcode----70场双周赛(5971.打折购买糖果的最小开销、5972.统计隐藏数组数目)


第一次参加周赛,费死劲A了两道。以后希望可以坚持参加周赛。

5971.打折购买糖果的最小开销

问题:一家商店正在打折销售糖果。每购买 两个 糖果,商店会 免费 送一个糖果。

免费送的糖果唯一的限制是:它的价格需要小于等于购买的两个糖果价格的 较小值

  • 比方说,总共有 4 个糖果,价格分别为 1234 ,一位顾客买了价格为 23 的糖果,那么他可以免费获得价格为 1 的糖果,但不能获得价格为 4 的糖果。

给你一个下标从 0 开始的整数数组 cost ,其中 cost[i] 表示第 i 个糖果的价格,请你返回获得 所有 糖果的 最小 总开销。

示例:

输入:cost = [1,2,3]
输出:5
解释:我们购买价格为 2 和 3 的糖果,然后免费获得价格为 1 的糖果。
总开销为 2 + 3 = 5 。这是开销最小的 唯一 方案。
注意,我们不能购买价格为 1 和 3 的糖果,并免费获得价格为 2 的糖果。
这是因为免费糖果的价格必须小于等于购买的 2 个糖果价格的较小值。

输入:cost = [6,5,7,9,2,2]
输出:23
解释:最小总开销购买糖果方案为:
- 购买价格为 9 和 7 的糖果
- 免费获得价格为 6 的糖果
- 购买价格为 5 和 2 的糖果
- 免费获得价格为 2 的最后一个糖果
因此,最小总开销为 9 + 7 + 5 + 2 = 23 。

输入:cost = [5,5]
输出:10
解释:由于只有 2 个糖果,我们需要将它们都购买,而且没有免费糖果。
所以总最小开销为 5 + 5 = 10 。

思路:先排序,然后从后往前遍历,三个三个一组,第三个免费,若不足三个,则这组没有可以免费得到的。

class Solution {
    public int minimumCost(int[] cost) {
        Arrays.sort(cost);
        
        int minCost = 0, count = 1;
        for(int i = cost.length - 1; i >= 0; i--){
            if(count % 3 != 0){
                minCost += cost[i];
            }
            count++;
        }
        return minCost;
    }
}

5972.统计隐藏数组数目

问题:给你一个下标从 0 开始且长度为 n 的整数数组 differences ,它表示一个长度为 n + 1隐藏 数组 相邻 元素之间的 差值 。更正式的表述为:我们将隐藏数组记作 hidden ,那么 differences[i] = hidden[i + 1] - hidden[i]

同时给你两个整数 lowerupper ,它们表示隐藏数组中所有数字的值都在 区间 [lower, upper] 之间。

  • 比方说,differences = [1, -3, 4]lower = 1upper = 6 ,那么隐藏数组是一个长度为 4 且所有值都在 16 (包含两者)之间的数组。
    • [3, 4, 1, 5][4, 5, 2, 6] 都是符合要求的隐藏数组。
    • [5, 6, 3, 7] 不符合要求,因为它包含大于 6 的元素。
    • [1, 2, 3, 4] 不符合要求,因为相邻元素的差值不符合给定数据。

请你返回 符合 要求的隐藏数组的数目。如果没有符合要求的隐藏数组,请返回 0

示例:

输入:differences = [1,-3,4], lower = 1, upper = 6
输出:2
解释:符合要求的隐藏数组为:
- [3, 4, 1, 5]
- [4, 5, 2, 6]
所以返回 2 。

输入:differences = [3,-4,5,1,-2], lower = -4, upper = 5
输出:4
解释:符合要求的隐藏数组为:
- [-3, 0, -4, 1, 2, 0]
- [-2, 1, -3, 2, 3, 1]
- [-1, 2, -2, 3, 4, 2]
- [0, 3, -1, 4, 5, 3]
所以返回 4 。

输入:differences = [4,-7,2], lower = 3, upper = 6
输出:0
解释:没有符合要求的隐藏数组,所以返回 0 。

思路:

  • 首先是暴力解,隐藏数组的本质就是,从[lower, upper]区间的某个数开始,依次加上differences数组的值,若计算过程中,每个元素的值都在[lower, upper]区间内,则算是一种合法的隐藏数组情况。但是超时了。
class Solution {
    private int res;
    public int numberOfArrays(int[] differences, int lower, int upper) {
        res = 0;
        for(int i = lower; i <= upper; i++){
            helper(differences, i, lower, upper, 0);
        }
        return res;
    }
    
    private void helper(int[] choice, int num, int lower, int upper, int index){
        if(num < lower || num > upper){
            return;
        }
        
        if(index == choice.length){
            res++;
            return;
        }
        
        helper(choice, num + choice[index],lower, upper, index + 1);
    }
}
  • 我们并不需要求这个隐藏数组的具体值,只需要判断以某个数开头的隐藏数组是否存在。怎么判断呢?计算出differences数组的前缀和,然后找到前缀和中的最大值max和最小值min,对于前元素i来说,若(i + min) >= lower && (i + max) <= upper,则以i开头的隐藏数组是存在的。否则不存在。
  • 为什么这样可以计算出来呢,前面说了,隐藏数组中的元素是这样来的:从[lower, upper]区间的某个数开始,依次加上differences数组的值。也就是说对于i来说,i依次加上前缀和中对应的值就可以得到隐藏数组的各个元素。前面说了,我们并不需要求这个隐藏数组的具体值,只需要判断以某个数开头的隐藏数组是否存在。若i+前缀和中的最小值都大于等于lower,则以i开始的隐藏数组的每个元素都大于等于lower,同理,若i+前缀和中的最大值都小于等于upper,则以i开始的隐藏数组的每个元素都小于等于upper。同时满足这两个条件,说明以i开始的隐藏数组是存在的。
class Solution {
    public int numberOfArrays(int[] differences, int lower, int upper) {
        int res = 0;
        int sum = 0, min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
        for(int j = 0; j < differences.length; j++){
            sum += differences[j];
            min = Math.min(min, sum);
            max = Math.max(max, sum);
        }
        
        for(int i = lower; i <= upper; i++){
            if((i + min) >= lower && (i + max) <= upper){
                res++;
            }
        }
        return res;
    }
}

整理思路,记录博客,以便复习。若有误,望指正~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值