Java LeetCode:吃N个橙子的最少天数
我今天在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
- 吃一个橘子
- 如果剩余的橙子数(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;
}