LeetCode | 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?

 

题目描述

给你一个下标从 0 开始的正整数数组 candiesCount ,其中 candiesCount[i] 表示你拥有的第 i 类糖果的数目。同时给你一个二维数组 queries ,其中 queries[i] = [favoriteTypei, favoriteDayi, dailyCapi] 。

 

你按照如下规则进行一场游戏:

  • 你从第 0 天开始吃糖果。

  • 你在吃完所有第 i - 1 类糖果之前,不能吃任何一颗第 i 类糖果。

  • 在吃完所有糖果之前,你必须每天至少吃一颗糖果。

请你构建一个布尔型数组 answer ,满足 answer.length == queries.length 。answer[i] 为 true 的条件是:在每天吃不超过 dailyCapi 颗糖果的前提下,你可以在第 favoriteDayi 天吃到第 favoriteTypei 类糖果;否则 answer[i] 为 false 。注意,只要满足上面 3 条规则中的第二条规则,你就可以在同一天吃不同类型的糖果。

请你返回得到的数组 answer 。

 

示例 1:

输入:candiesCount = [7,4,5,3,8], queries = [[0,2,2],[4,2,4],[2,13,1000000000]]

输出:[true,false,true]

提示:

1- 在第 0 天吃 2 颗糖果(类型 0),第 1 天吃 2 颗糖果(类型 0),第 2 天你可以吃到类型 0 的糖果。

2 - 每天你最多吃 4 颗糖果。即使第 0 天吃 4 颗糖果(类型 0),第 1 天吃 4 颗糖果(类型 0 和类型 1),你也没办法在第 2 天吃到类型 4 的糖果。换言之,你没法在每天吃 4 颗糖果的限制下在第 2 天吃到第 4 类糖果。

3 - 如果你每天吃 1 颗糖果,你可以在第 13 天吃到类型 2 的糖果。

 

示例 2:

输入:candiesCount = [5,2,6,4,1], queries = [[3,1,2],[4,10,3],[3,10,100],[4,100,30],[1,3,1]]

输出:[false,true,true,false,false]

 

提示:

  • 1 <= candiesCount.length <= 10^5

  • 1 <= candiesCount[i] <= 10^5

  • 1 <= queries.length <= 10^5

  • queries[i].length == 3

  • 0 <= favoriteTypei < candiesCount.length

  • 0 <= favoriteDayi <= 10^9

  • 1 <= dailyCapi <= 10^9

 

 

题目链接:https://leetcode-cn.com/problems/can-you-eat-your-favorite-candy-on-your-favorite-day/

 

题目描述就是上面那样,有点长,也是看了几遍才看懂题意,多看两遍就懂了。老哥们把我想说的话都说了↓↓↓↓↓↓

图片

 

解题思路

就一句话:算出想吃的糖最少和最多分别需要多少天能吃到,然后判断 favoriteDay 是不是在这俩数的范围内。

好的就是这样。

但是真正写起代码来,还是废了不少时间的↓↓↓↓↓

这这这这这么长一串提交记录......

 

图片

 

按我写的版本一版一版来,看看最后是如何 AC 的。

 

ver 1.0

class Solution {
    public boolean[] canEat(int[] candiesCount, int[][] queries) {
        boolean[] res = new boolean[queries.length];

        for (int i = 0 ; i < queries.length ; i++){
            res[i] = canEat(candiesCount, queries[i]);
        }

        return res;
    }

    private boolean canEat(int[] candiesCount, int[] query) {
        int dailyCap = query[2]; // 每天最多吃的糖果数
        int favoriteDay = query[1];  // 想要在第 这么多天 吃到favoriteType类型的糖果
        int favoriteType = query[0]; // 想要吃的糖果类型

        int min = 0;
        for (int i = 0 ; i < favoriteType ; i++){
            min += candiesCount[i];
        }

        min = min/dailyCap;

        int max = 0;
        for(int i = 0 ; i <= favoriteType; i++) {
            max+=candiesCount[i];
        }

        return favoriteDay >= min && favoriteDay < max;
    }
}

这是我最开始的解法,代码很好懂,但是超时。

 

我注意到,boolean canEat 函数中的两个 for 循环实际上是不必要的,可以将 min、max 放在同一个 for 循环中,因为它俩之间就差一个  candiesCount[favoriteType],于是有了下面的代码。

 

于是我继续改。

 

ver 2.0

class Solution {
    public boolean[] canEat(int[] candiesCount, int[][] queries) {
        boolean[] res = new boolean[queries.length];

        for (int i = 0 ; i < queries.length ; i++){
            res[i] = canEat(candiesCount, queries[i]);
        }

        return res;
    }

    private boolean canEat(int[] candiesCount, int[] query) {
        int dailyCap = query[2]; // 每天最多吃的糖果数
        int favoriteDay = query[1];  // 想要在第 这么多天 吃到favoriteType类型的糖果
        int favoriteType = query[0]; // 想要吃的糖果类型
        
        int max = 0;
        for (int i = 0 ; i <= favoriteType ; i++){
            max += candiesCount[i];
        }
        return favoriteDay >= (max-candiesCount[favoriteType])/dailyCap && favoriteDay < max;
    }
}

 

直接将 min 去掉了,max - candiesCount[favoriteType] 就是 min。

但还是超时。

 

然后我就又陷入了思考,因为这个解法是 O(n^2) 的复杂度,既然 n^2 都超时了,那么自然是想着看看能不能优化到 O(n) 的复杂度去。答案是可以的。

 

注意到,上面实际上是有不必要的重复操作的,就是针对每一个 query,都会去加一遍 max,都是从 0 开始加,这自然是一种不必要的操作,于是就有了下面的解法↓↓↓↓↓↓

ver 3.0

class Solution {
    public boolean[] canEat(int[] candiesCount, int[][] queries) {
        boolean[] res = new boolean[queries.length];
        long[] prefixSum = new long[candiesCount.length];

        prefixSum[0] = candiesCount[0];
        for(int i = 1 ; i < candiesCount.length ; i++){
            prefixSum[i] = prefixSum[i-1] + candiesCount[i];
        }

        for (int i = 0 ; i < queries.length ; i++){
            int dailyCap = queries[i][2]; // 每天最多吃的糖果数
            int favoriteDay = queries[i][1];  // 想要在第 这么多天 吃到favoriteType类型的糖果
            int favoriteType = queries[i][0]; // 想要吃的糖果类型

            res[i] = favoriteDay >= (prefixSum[favoriteType] - candiesCount[favoriteType])/dailyCap && favoriteDay < prefixSum[favoriteType];
        }

        return res;
    }
}

加一个 prefixSum 数组,prefixSum[i] 表示的是 candiesCount 数组前 i 个和。这样就可以在 O(1) 的时间复杂度得到 ver1.0 中的 min 和 max 了。进而将算法优化到 O(n) 的复杂度,自然也是顺利通过啦!

 

就是这个效率嘛...... 有点不敢恭维......

管他呢,做出来就行!

图片

 

有一个需要注意的点是:prefixSum 数组的值会超过 int 表示范围,所以这里用 long 型。


 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值