我描述了我的代码,发现我的程序花了大约85%的时间执行这个特定的递归函数。该函数旨在计算在给定初始位置(x,y)的情况下到达马尔可夫链中的一组状态的概率。
private static boolean condition(int n){
int i = 0;
while ( n >= i){
if( n == i*4 || n == (i*4 - 1))
return true;
i++;
}
return false;
}
public static double recursiveVal(int x, int y, double A, double B){
if(x> 6 && (x- 2 >= y)){ return 1;}
if(y> 6 && (y- 2 >= x)){ return 0;}
if(x> 5 && y> 5 && x== y){ return (A*(1-B) / (1 -(A*B) - ((1-A)*(1-B))));}
if(condition(x+ y)){
return (recursiveVal(x+1, y,A,B)*A + recursiveVal(x, y+1,A,B)*(1-A));
}
else{
return (recursiveVal(x+1, y,A,B)*(1-B) + recursiveVal(x,y+1,A,B)*B);
}
}
我曾被告知,99%的递归函数可以被while循环替换。我做这件事虽然困难。有谁知道如何改进执行时间或将其重写为迭代循环?
由于
答案 0 :(得分:7)
您可以尝试使用一种名为memoization的技术,该技术基本上会缓存先前为递归调用计算的结果。
作为旁注,我建议稍微重新格式化您的代码。这是yoru代码的简化版本。
private static boolean condition(int n){
for (int i = 0; i <= n; i++)
if(n == i*4 || n == (i * 4 - 1))
return true;
return false;
}
public static double recursiveVal(int x, int y, double A, double B){
if (x > 6 && (x - 2 >= y))
return 1;
if (y > 6 && (y - 2 >= x))
return 0;
if(x > 5 && y > 5 && x == y)
return A*(1-B) / (1 -(A*B) - ((1-A)*(1-B)));
double val1 = recursiveVal(x+1, y, A, B);
double val2 = recursiveVal(x, y+1, A, B);
return condition(x + y)
? A * val1 + val2 * (1-A)
: (1-B) * val1 + B * val2;
}
答案 1 :(得分:0)
要将其转换为迭代形式,请注意您正在计算两个(离散)变量的函数。您可以使用表来存储函数的值,并按特定顺序填写表,以便在需要时已经计算出所需的值。 (在这种情况下,来自x
和y
)的较高值。
在这种情况下,边界情况(对应于原始递归中的基本情况)是:
f(7, y..5), f(8, 6)
f(x..5, 7), f(6, 8)
f(7, 7)
然后我们填写f(7, 6)
和f(6, 7)
,然后“向下”继续 - 即
f(6,6),f(5,6)... f(x,6),f(6,5),f(5,5)... f(x,5)... f( x,y)。
请注意,看起来像函数调用语法的对应于表查找(它实际上转换为数组语法)。
答案 2 :(得分:0)
如果要将递归函数重构为迭代函数,步骤如下:
1)确定递归的基本情况。达到基本情况时,会导致递归结束。每个递归必须具有已定义的基本情况。此外,每个递归调用必须在基本情况下取得进展(否则将无限执行递归调用)。
2)实现一个循环,迭代直到达到基本情况 3)在基础案例方面取得进展。将新参数发送到循环顶部而不是递归方法。
答案 3 :(得分:0)
如何尝试理解它正在做什么可以使代码更快/更简单......
这种方法试图确定'n'是4的倍数还是n + 1是4的倍数。这可以写得更短。
private static boolean condition(int n){
return (n+1) & 3 <= 1;
}