Java LeetCode:吃N个橙子的最少天数

Java LeetCode:吃N个橙子的最少天数,java,recursion,Java,Recursion,我今天在Leetcode竞赛中遇到了这个问题,我已经为这个问题编写了一个代码,但它不起作用,有人能告诉我我缺少了什么条件吗 问题链接: 问题:- 厨房里有n个橙子,你决定每天吃其中一些,如下所示: 吃一个橘子 如果剩余的橙子数(n)可以被2整除,那么你可以吃n/2个橙子 如果剩余的橙子数(n)可以被3整除,那么你可以吃2*(n/3)个橙子。每天只能选择一个操作 返回吃n个橙子的最小天数 我的解决方案: class Solution { static int Norange(int n, in

我今天在Leetcode竞赛中遇到了这个问题,我已经为这个问题编写了一个代码,但它不起作用,有人能告诉我我缺少了什么条件吗

问题链接:

问题:-

厨房里有n个橙子,你决定每天吃其中一些,如下所示:

  • 吃一个橘子
  • 如果剩余的橙子数(n)可以被2整除,那么你可以吃n/2个橙子
  • 如果剩余的橙子数(n)可以被3整除,那么你可以吃2*(n/3)个橙子。每天只能选择一个操作

返回吃n个橙子的最小天数

我的解决方案:

class Solution {
static int Norange(int n, int days){
    
    //no more oranges left
    if(n <= 0)
        return days;
    
    //increment days
    ++days;
    
    //divisible by 2
    if(n % 2 == 0)
        return Math.min(Norange(n - 1 , days), Norange(n/2, days));
    
    //not divisible by 2 and 3
    else if( n % 2 != 0 && n % 3 != 0)
        return Norange(n - 1, days);
    
    //divisible by 3
    return Math.min(Norange(n - 1, days), Norange( n - 2*(n/3), days ));
}

public int minDays(int n) {
    
    return Norange(n, 0);
    
}
类解决方案{
静态整数范围(整数n,整数天){
//橘子不剩了

如果(n我想这会更干净

public class OrangeInDays {
    
    static int days;

    public static void main(String[] args) {
        
        System.out.println(minDays());
        
    }
    
    
    private static int minDays() {
        countDays(293);
        return days;
    }


    public static void countDays(int orng) {
        
        if(orng !=0 ) {
            if(orng%3 == 0) {
                
                orng -= 2*(orng/3);
                
            }
            else if(orng%2 ==0 && orng%3 != 1) {
                
                orng -= orng/2; 
            }else if(orng%2 ==0 && ((orng-1)/3)%2!=0 && ((orng-1)/3)%3!=0) {
                orng -= orng/2;
            }
            else {
                orng--;
            }

            countDays(orng);
            days++;
        }
        
    }

}

正如@WJS在他们现在删除的答案中所说的,你不能接受
n
可以被2和3整除的情况。然而,值得赞扬的是,你似乎认识到贪婪的算法是不起作用的——在给定的一天只吃一个橙子有时是正确的,即使有两个以上的橙子可用。你可以d通过对代码进行相对较小的调整来适应六个问题的倍数:

static int Norange(int n, int days){
    
    //no more oranges left
    if(n <= 0)
        return days;
    
    //increment days
    ++days;

    int min = Norange(n - 1 , days);
    
    //divisible by 2
    if(n % 2 == 0)
        min = Math.min(min, Norange(n/2, days));
    
    //divisible by 3
    if(n % 3 == 0)
        min = Math.min(min, Norange( n - 2*(n/3), days ));

    return min;
}
static int Norange(int n,int天){
//橘子不剩了

如果(n,则更容易编写自底向上的dp解或相同的递归解。 但对于更多的人来说,这是行不通的。 在这个问题中,n可能高达2x10^9。计算dp中的所有状态将得到TLE。 所以,我们必须做一些修剪。当数量很大时,每天吃一个橙子是没有意义的。我们可以尝试将数量减少到可以被2或3整除的最接近的数字;然后可以食用n/2或2*n/3个橙子,并选择能提供最少天数的路径

下面是dp自下而上的代码

 public int minDaysBottomUp(int n) {
    if(n <2)return 1;
    int[] dp = new int[n+1];
    dp[1] =1;
    dp[2] = 2;

    for(int i =3; i <=n; i++){
        dp[i] =Integer.MAX_VALUE;
    }
    for(int i=3; i <=n; i++){
        
        if(i%3 ==0 && i%2 ==0 ){
            int a = i-2*(i/3);
            int b = i-(i/2);
            dp[i] =1+ Math.min(dp[i-1], Math.min(dp[a], dp[b]));
        }
        else if(i%3==0){
            int a = i-2*(i/3);
         //   System.out.println(" 3 "+ rem);
            dp[i] = 1+ Math.min(dp[i-1], dp[a]);         
            
        }else if ( i %2==0){
            int b = i-(i/2);
       
            dp[i]= 1+Math.min(dp[i-1], dp[b]);
        }
        dp[i] = Math.min(dp[i], 1+dp[i-1]);
        

    }
    return dp[n];

}
public int minDaysBottomUp(int n){

如果(n我相信作者想做一个递归的解决方案。你怎么知道的?好吧,OP的尝试是一个递归的解决方案,OP在问题中包含了一个
递归
标记。虽然现在它是递归的,但也有一个问题,这给了一些输入错误的答案。这个练习不适合贪婪的解决方案:有时,最佳的移动是只吃一个橙子,即使剩下两个以上。例如,以10作为输入,该方法产生五天(10 ->5>4>2>1>0),但最优解只需四天(10 ->9>3>3>)。。此外,仅使用代码的答案在这里往往不受重视。我们喜欢代码,但我们更喜欢看到一些散文来解释涉及的因素,并描述代码如何解决这些问题。是否需要递归解决方案?发布链接非常有帮助(尤其是当您需要帐户查看信息时)。请确保您发布了挑战的
确切的
措辞和要求。请谨慎,因为此帖子可能会因侵犯版权而被删除。我以前见过代码挑战网站这样做。Java命名约定有以小写字母(nOrange)开头的方法和变量,而类以大写字母开头。我想补充一个问题,n从1到2*10^9不等。记忆和制表算法给出3681069等值的TLE。有人能给出算法吗?是的。我删除了我的答案,因为我的假设很幼稚。但有趣的问题。回到绘图板。这个解决方案工作得很好,对任何输入都不会给出错误的答案,但正如您所提到的,对于像673这样的大输入,它确实给出了时间限制超过错误。我很好奇它需要多少递归调用,所以我在方法的开头放了一个静态计数器。对于
673
它需要
1701575892调用。从后续的澄清意见中,我不认为673个大的“代码>N<代码”的值。在哪里<代码> MyDays<代码>最小的进食天数,橙色相同的Nangange-()?@ WJS<代码> Norange <代码>有两个参数。优化方法中的第二个是什么?
  Map<Integer, Integer> map = new HashMap<>();
public int minDaysOptimized(int n){
    if(n <=1) return n;
    if(map.containsKey(n))return map.get(n);
    
     int ans = 1 + Math.min(n%2 + minDays(n/2), n%3+ minDays(n/3));
     map.put(n, ans);
     return ans;
        
    
}