我正在解决一个似乎需要某种回溯的问题。我有一个有效的递归方法,但stackOverFlow发生在较大的输入中。可以通过迭代实现解决吗?我正在尝试实现一个采用两个目标值a和b的方法。从a = 1和b = 1开始,要达到目标a和b值需要多少次“加法”?加法可以使a = a + b或b = b + a,但不能两者都做。 例如,如果目标a = 2和目标b = 1,则需要1个“加”。 a = 1&b = 1,a = a + b =2。
public static String answer(String M, String F) {
return answerRecur(new BigInteger(M), new BigInteger(F), 0);
}
public static String answerRecur(BigInteger M, BigInteger F, int its) {
if(M.toString().equals("1") && F.toString().equals("1")) {
return "" + its;
}
else if(M.compareTo(new BigInteger("0")) <=0 || F.compareTo(new BigInteger("0")) <=0) {
return "impossible";
}
String addM = answerRecur(M.subtract(F), F, its +1);
String addF = answerRecur(M, F.subtract(M), its +1);
if(!addM.equals("impossible")) {
return addM;
}
if(!addF.equals("impossible")) {
return addF;
}
return "impossible";
}
答案 0 :(得分:0)
递归回溯通过遍历所有候选步骤,执行步骤,递归和撤消该步骤来进行。
这意味着,如果一个解决方案包含N个项目,则理想情况下,递归深度不会超过N。
所以:预计不会发生溢出,可能会尝试过多,甚至无限地重复发生。
但是,在您的情况下,BigInteger可能足够大,而当使用较小的步骤(1)时,递归深度会非常大。每个电话都会产生足够的收益。最好是int或long而不是BigInteger。
在每个电话中,您都有两个候选人:
您对两者都进行了评估,发现结果可能会停止。
缺少(数学上的!)智力:很好的办法是防止太多的步骤,尽可能地找到解决方案。通常,这可以通过对(2)个候选者进行排序的方式来实现。
如何提供一种智能解决方案?首先,数学必须是可读的,而BigInteger则少。手动尝试一些示例解决方案,然后寻找一种 smart 方法来对尝试进行排序。
假设M和F保持正数,您可以缩短递归:
if (M.compareTo(BigInteger.ZERO) <= 0 || F.compareTo(BigInteger.ZERO) <= 0) {
return "impossible";
}
if (M.equals(BigInteger.ONE)) {
return String.valueOf(F.intValue() - 1 + its);
}
if (F.equals(BigInteger.ONE)) {
return String.valueOf(M.intValue() - 1 + its);
}
对于整数除法(和取模)可以做到这一点:
if (M.compareTo(F) > 0) {
String addM = answerRecur(M.mod(F), F, its + M.divided(F).intValue());
}
尽管有多个递归调用,实际上仍然可以考虑使用迭代解决方案,但这不会增加质量。
备注:
f
和m
。