【发布时间】:2018-07-22 21:10:21
【问题描述】:
我在编写干净的代码与性能开销之间存在小冲突。
假设我正在扫描一个 NxN 数组,在 JAVA 中使用递归,并且我唯一的停止条件是停留在数组边界内。
我可以把函数写成这样,更简洁易读:
private void move(int x, int y){
if(outOfBound(x,y)){ \\ stopping condition
return;
}
move(x+1, y);
move(x, y+1);
move(x-1, y);
move(x, y-1);
}
或者我可以这样写:
private void move(int x, int y){
if(!outOfBound(x+1,y)){ \\ stopping condition
move(x+1, y);
}
if(!outOfBound(x,y+1)){ \\ stopping condition
move(x, y+1);
}
if(!outOfBound(x-1,y)){ \\ stopping condition
move(x-1, y);
}
if(!outOfBound(x,y-1)){ \\ stopping condition
move(x, y-1);
}
}
据我所知,可以节省 4N 次递归调用(4N 个新堆栈帧)。
那么,为了避免不必要的调用,编写第二个函数会“更正确”吗?
【问题讨论】:
-
1) 如果这两个版本应该是等效的,那么您将缺少一些
nots。 2)为什么你认为你的第二个版本可以节省任何电话?由于x和y在给定的递归级别上是不变的,所以isCondition(x,y)应该在所有四种情况下产生相同的结果,并且递归调用要么作为一个集合一起发生,要么不一起发生。版本 1 更简洁,避免了对isCondition的冗余调用。 -
- 当然,除非后续
isCondition调用的结果确实取决于对move的调用,在这种情况下,版本 1 的逻辑无论如何都是不正确的。 -
@pjs,这是一个错误,我编辑了第二个函数。希望现在很清楚。
-
以最易读的方式编写会更正确。如果它成为性能问题,您可以对其进行分析并稍后进行更改。
-
我认为您不会遇到性能问题,因为如果超出范围,则调用是
O(1)空间和时间复杂度,而您会追求更高的空间和时间复杂度。 . 在它继续的情况下,这将是你的问题,而不是它何时终止。
标签: performance recursion readability