[题解]LeetCode 1553. 吃掉 N 个橘子的最少天数(C++)(腾讯笔试题)

题目

厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子:

吃掉一个橘子。
如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。
如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。
每天你只能从以上 3 种方案中选择一种方案。

请你返回吃掉所有 n 个橘子的最少天数。

示例 1:

输入:n = 10
输出:4
解释:你总共有 10 个橘子。
第 1 天:吃 1 个橘子,剩余橘子数 10 - 1 = 9。
第 2 天:吃 6 个橘子,剩余橘子数 9 - 2*(9/3) = 9 - 6 = 3。(9 可以被 3 整除)
第 3 天:吃 2 个橘子,剩余橘子数 3 - 2*(3/3) = 3 - 2 = 1。
第 4 天:吃掉最后 1 个橘子,剩余橘子数 1 - 1 = 0。
你需要至少 4 天吃掉 10 个橘子。

示例 2:

输入:n = 6
输出:3
解释:你总共有 6 个橘子。
第 1 天:吃 3 个橘子,剩余橘子数 6 - 6/2 = 6 - 3 = 3。(6 可以被 2 整除)
第 2 天:吃 2 个橘子,剩余橘子数 3 - 2*(3/3) = 3 - 2 = 1。(3 可以被 3 整除)
第 3 天:吃掉剩余 1 个橘子,剩余橘子数 1 - 1 = 0。
你至少需要 3 天吃掉 6 个橘子。

示例 3:

输入:n = 1
输出:1

示例 4:

输入:n = 56
输出:6

提示:

  • 1 <= n <= 2*10^9

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

思路

2021年8月27日腾讯游戏客户端公开课笔试编程第一题,败北,反思ing
这题我一开始以为是很简单的贪心题,下意识认为“若\(n_1 < n_2\),则吃完\(n_1\)个橘子要用的天数肯定比吃\(n_2\)个橘子少”,然而这个命题是假的!只要想一下n = 5和n = 9就立即能明白了。结果我笔试的时候脑子宕机了根本没想到自己的思路有问题
既然不能用贪心,那就要用到动态规划的思想了!然而我在这里又跳进一个大坑,一开始想的是维护一个vector,从0到n算出每个数对应的最少天数,结果当然是超时!呵呵,O(n)的时间复杂度也超时。行呀,不做了
既然O(n)也超时,那就考虑有没有O(log(n))级别的算法吧。偷看题解可以用记忆化搜索+自顶向下递归,因为有公式
minDays(n) = 1 + min[ (n%2) + minDays(n/2), (n%3) + minDays(n/3) ]
成立,同时每次递归搜索都把值存入一个哈希表防止重复计算。
时间复杂度\(O(log^2(n))\),空间复杂度\(O(log^2(n))\)。证明相当复杂,有兴趣的可以看官方题解证明。

代码

class Solution {
public:
    int minDays(int n) {
        if(n <= 2) return n;
        if(mp.count(n)) return mp[n];
        return mp[n] = 1 + min(n%2 + minDays(n/2), n%3 + minDays(n/3));
    }

private:
    unordered_map<int, int> mp;
};

[题解]LeetCode 1553. 吃掉 N 个橘子的最少天数(C++)(腾讯笔试题)

上一篇:scrapy框架使用-crawlspider类


下一篇:[题解]剑指 Offer 41. 数据流中的中位数(C++)