使用记忆的 Tribonacci 实现:运行时错误
Tribonnaci implementation using memoization: Runntime error
大家好,我试图在 java 中实现 tribonaci 的解决方案,你们中的许多人可能都熟悉动态程序迷你课程中的这个 leetcode 任务。
基本上在 tribonaci t0 = 0 t1 = t2 = 1 和 tn = t(n - 3) + t(n-2) + t(n-1) 内。
我试图通过使用 hasmap 和记忆(从上到下)的递归解决方案来实现它。
但是,当我 运行 代码时,出现运行时错误。任何人都可以帮我查明来源吗?提前谢谢你
class Solution {
private HashMap<Integer,Integer> memo = new HashMap<Integer,Integer>();
private int n;
private int dp(int i){
if (n == 0) return 0;
if (n == 1 || n == 2) return 1;
if(!memo.containsKey(i)){
memo.put(i,dp(i - 1) + dp(i - 2) + dp(i - 3));
}
return memo.get(i);
}
public int tribonacci(int n) {
this.n = n;
return dp(n);
}
}
问题是您没有达到递归的 end/bottom。你写了它,tribonacci 是 - tn = t(n - 3) + t(n-2) + t(n-1)
,但在你的代码中你做相反的事情 - dp(n) + dp(n + 1) + dp(n + 2)
,而不是对前 3 个值求和,而是对当前值和 2 个下一个值求和。想象一下——您需要向后退以获取已经计算出的值,但在您的代码中您前进到下一个值,但它们并不存在。这就是导致递归无底并连续到 Whosebugerror
.
的原因
这里是代码,经过修改和简化。
public class Tribonnaci {
private final HashMap<Integer,Integer> memo;
public Tribonnaci() {
this.memo = this.initMap();
}
private HashMap<Integer, Integer> initMap() {
//init map, this will be bottom of your recursion
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 0);
map.put(1, 1);
map.put(2, 1);
//also, cleaner, your bottom is the memoized values
//not combination of it and if checks
return map;
}
private int calculateNthTribonacci(int n){
Integer result = this.memo.get(n);
//if result is null, that means it has not been calculated before
if (result == null) {
//sum the three previous values from tribonnaci sequence
result = this.calculateNthTribonacci(n - 1) + this.calculateNthTribonacci(n - 2) + this.calculateNthTribonacci(n - 3);
//save it in memo
this.memo.put(n, result);
}
return result;
}
public int tribonacci(int n) {
return calculateNthTribonacci(n);
}
}
编辑:好的,现在问题是实例变量private int n;
。您不使用实例变量来检查递归 bottom
if (n == 0) return 0;
if (n == 1 || n == 2) return 1;
到达底部时必须检查方法参数。递归是在该方法内部调用相同的方法,但给它不同的参数。在您的情况下,这是 i
:
private int dp(int i)
这就是为什么您需要检查 i
的值以到达递归底部并删除实例变量 n
。像这样:
public class Tribonnaci {
private HashMap<Integer, Integer> memo = new HashMap<Integer, Integer>();
private int dp(int i) {
if (i == 0) return 0;
if (i == 1 || i == 2) return 1;
if (!memo.containsKey(i)) {
int prev = dp(i - 1);
int prevPrev = dp(i - 2);
int prevPrevPrev = dp(i - 3);
int value = prev + prevPrev + prevPrevPrev;
memo.put(i, value);
}
return memo.get(i);
}
public int tribonacci(int n) {
return dp(n);
}
}
我故意写得冗长,调试了几次以更好地理解递归的工作原理。
大家好,我试图在 java 中实现 tribonaci 的解决方案,你们中的许多人可能都熟悉动态程序迷你课程中的这个 leetcode 任务。 基本上在 tribonaci t0 = 0 t1 = t2 = 1 和 tn = t(n - 3) + t(n-2) + t(n-1) 内。 我试图通过使用 hasmap 和记忆(从上到下)的递归解决方案来实现它。 但是,当我 运行 代码时,出现运行时错误。任何人都可以帮我查明来源吗?提前谢谢你
class Solution {
private HashMap<Integer,Integer> memo = new HashMap<Integer,Integer>();
private int n;
private int dp(int i){
if (n == 0) return 0;
if (n == 1 || n == 2) return 1;
if(!memo.containsKey(i)){
memo.put(i,dp(i - 1) + dp(i - 2) + dp(i - 3));
}
return memo.get(i);
}
public int tribonacci(int n) {
this.n = n;
return dp(n);
}
}
问题是您没有达到递归的 end/bottom。你写了它,tribonacci 是 - tn = t(n - 3) + t(n-2) + t(n-1)
,但在你的代码中你做相反的事情 - dp(n) + dp(n + 1) + dp(n + 2)
,而不是对前 3 个值求和,而是对当前值和 2 个下一个值求和。想象一下——您需要向后退以获取已经计算出的值,但在您的代码中您前进到下一个值,但它们并不存在。这就是导致递归无底并连续到 Whosebugerror
.
这里是代码,经过修改和简化。
public class Tribonnaci {
private final HashMap<Integer,Integer> memo;
public Tribonnaci() {
this.memo = this.initMap();
}
private HashMap<Integer, Integer> initMap() {
//init map, this will be bottom of your recursion
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 0);
map.put(1, 1);
map.put(2, 1);
//also, cleaner, your bottom is the memoized values
//not combination of it and if checks
return map;
}
private int calculateNthTribonacci(int n){
Integer result = this.memo.get(n);
//if result is null, that means it has not been calculated before
if (result == null) {
//sum the three previous values from tribonnaci sequence
result = this.calculateNthTribonacci(n - 1) + this.calculateNthTribonacci(n - 2) + this.calculateNthTribonacci(n - 3);
//save it in memo
this.memo.put(n, result);
}
return result;
}
public int tribonacci(int n) {
return calculateNthTribonacci(n);
}
}
编辑:好的,现在问题是实例变量private int n;
。您不使用实例变量来检查递归 bottom
if (n == 0) return 0;
if (n == 1 || n == 2) return 1;
到达底部时必须检查方法参数。递归是在该方法内部调用相同的方法,但给它不同的参数。在您的情况下,这是 i
:
private int dp(int i)
这就是为什么您需要检查 i
的值以到达递归底部并删除实例变量 n
。像这样:
public class Tribonnaci {
private HashMap<Integer, Integer> memo = new HashMap<Integer, Integer>();
private int dp(int i) {
if (i == 0) return 0;
if (i == 1 || i == 2) return 1;
if (!memo.containsKey(i)) {
int prev = dp(i - 1);
int prevPrev = dp(i - 2);
int prevPrevPrev = dp(i - 3);
int value = prev + prevPrev + prevPrevPrev;
memo.put(i, value);
}
return memo.get(i);
}
public int tribonacci(int n) {
return dp(n);
}
}
我故意写得冗长,调试了几次以更好地理解递归的工作原理。