2022-04-29:厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子: 吃掉一个橘子。 如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。 如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。 每天你只能从以上 3 种方案中选择一种方案。 请你返回吃掉所有 n 个橘子的最少天数。 输入: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 个橘子。 力扣1553. 吃掉 N 个橘子的最少天数。 来自腾讯。

答案2022-04-29:

能按比例吃的时候,绝不一个一个吃。递归。1/3和1/2取最小值。

代码用rust编写。代码如下:

use std::collections::HashMap;

fn main() {
    // 所有的答案都填在这个表里
    // dp这个表对所有的过程共用
    // 左神代码里,dp是全局变量。rust里没找到实现的方法。故采用传参的方式。
    let mut dp: HashMap<isize, isize> = HashMap::new();
    let n: isize = 10;
    let ans = min_days(n, &mut dp);
    println!("ans = {}", ans);
}

fn min_days(n: isize, dp: &mut HashMap<isize, isize>) -> isize {
    if n <= 1 {
        return n;
    }
    if let Some(x) = dp.get(&n) {
        return *x;
    }

    // 1) 吃掉一个橘子
    // 2) 如果n能被2整除,吃掉一半的橘子,剩下一半
    // 3) 如果n能被3正数,吃掉三分之二的橘子,剩下三分之一
    // 因为方法2)和3),是按比例吃橘子,所以必然会非常快
    // 所以,决策如下:
    // 可能性1:为了使用2)方法,先把橘子吃成2的整数倍,然后直接干掉一半,剩下的n/2调用递归
    // 即,n % 2 + 1 + minDays(n/2)
    // 可能性2:为了使用3)方法,先把橘子吃成3的整数倍,然后直接干掉三分之二,剩下的n/3调用递归
    // 即,n % 3 + 1 + minDays(n/3)
    // 至于方法1),完全是为了这两种可能***的,因为能按比例吃,肯定比一个一个吃快(显而易见的贪心)
    let ans = get_min(
        n % 2 + 1 + min_days(n / 2, dp),
        n % 3 + 1 + min_days(n / 3, dp),
    );
    dp.insert(n, ans);
    return ans;
}

fn get_min(a: isize, b: isize) -> isize {
    if a < b {
        a
    } else {
        b
    }
}

执行结果如下:

在这里插入图片描述


左神java代码