【问题标题】:Recursion - clean code vs performance递归 - 干净的代码与性能
【发布时间】: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)为什么你认为你的第二个版本可以节省任何电话?由于xy 在给定的递归级别上是不变的,所以isCondition(x,y) 应该在所有四种情况下产生相同的结果,并且递归调用要么作为一个集合一起发生,要么不一起发生。版本 1 更简洁,避免了对 isCondition 的冗余调用。
  • - 当然,除非后续 isCondition 调用的结果确实取决于对 move 的调用,在这种情况下,版本 1 的逻辑无论如何都是不正确的。
  • @pjs,这是一个错误,我编辑了第二个函数。希望现在很清楚。
  • 以最易读的方式编写会更正确。如果它成为性能问题,您可以对其进行分析并稍后进行更改。
  • 我认为您不会遇到性能问题,因为如果超出范围,则调用是O(1) 空间和时间复杂度,而您会追求更高的空间和时间复杂度。 . 在它继续的情况下,这将是你的问题,而不是它何时终止。

标签: performance recursion readability


【解决方案1】:

只有一种方法可以解决这个难题 - 在实际项目环境中衡量性能。

如果这严重影响了现实生活场景中的性能,并成为瓶颈,请务必将其更改为不太理想的那个。

另一方面,如果它对您的应用的整体性能没有真正的影响,那就让它更干净。一个由于脏代码而引入的错误可能会以纯美元计算比与稍微脏一点的代码相关的服务器成本要高得多。

【讨论】:

    猜你喜欢
    • 2018-08-26
    • 2010-10-28
    • 2010-11-13
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多