识别可以转换为递归方法的方法

时间:2015-06-16 11:03:01

标签: java recursion

我一直在四处寻找练习我的递归,但是我已经完成了在codingBat和其他一些方面的练习问题。如果您有更多建议,请随时评论!

我的问题是您如何确定何时可以简单地将方法转换为递归方法,即使您必须或可以更改参数?

所需的递归方法的元素是需要的基本情况,它认为递归的结束,以及循环或不循环的原因(恢复到基本情况)。我可能遗漏了递归方法的其他重要方面吗?

我发现的递归方法的一个例子(但尚未解决以便递归)如下所示。它来自codingBat,我不是要求任何人纠正我的代码。它只是一个可以转换的方法的例子,我发现了。我会搞清楚的。

编辑为答案。由于混淆删除了示例。 编写递归方法时需要注意的要求:

  1. StackOverFlow错误。
  2. 可以递归包含循环的所有方法,但它可能不是最佳实现选择。
  3. 递归方法应该自然来解决问题。

3 个答案:

答案 0 :(得分:5)

基本上,递归可以模拟每个循环,所以可以为包含循环的每个方法创建一个递归方法 - 然而不能保证递归版本将完成(因为您的循环版本可能使用状态来缓存结果,而您的递归版本没有)或甚至运行(因为您可能会获得StackOverflowError - 如何拟合)。

编辑:请注意,即使使用直接递归也可能导致堆栈溢出,有一种技术可以解决这个问题,即trampolining(文章适用于python,但也适用于Java 8的lambdas)。

编辑2:请注意迭代和递归解决方案之间的关系是由Church-Turing - 猜想引起的。

答案 1 :(得分:1)

总是可以将循环转换为递归(但不是相反):

// this is a general loop
for ( init(); loopCondition(); step() )
    body();

// this is the general recursion of such a loop
function rec(recursionCondition, body, step) {
    if(recursionCondition()) {
        body();
        step();
        rec(recursionCondition, body, step);
    }
}
// and don't forget to initialise at the calling level:
init();
rec(loopCondition, body, step);

例如

for(int i = 0; i < length; ++i)
    doStuffOn(i);

function doStuffRec(int i, int length) {
    if(i < length) { // recursionCondition
        doStuffOn(i); // body
        int nextI = i + 1; // step
        doStuffRec(nextI, length);
    }
}
// calling level (initialisation of i)
doStuffRec(0, length);

答案 2 :(得分:1)

基本上,您可以编写以递归或迭代方式循环的每个方法。你只需要一个条件来阻止循环。

有时,方法比迭代更容易实现递归。但值得注意的是运行时。

long fibonacci(long Parameter) {
  if(Parameter <=1)
    return 1;
  else
    return fibonacci(Parameter-1)+fibonacci(Parameter-2);
}

现在尝试为n=40找到这个,这需要很长时间。为什么?因为运行时复杂性是指数级的。意味着计算需要更长的时间。

将此与iterativ实现进行比较:

long fibonacciIterativ(long Parameter) {
  int a=1, b=1;
  for(int i=1; i<Parameter;i++) {
    a = a+b;
    b = a-b;
  }
  return a;
}

这里运行时复杂度是线性的,意味着运行时随输入线性增长。 (IIRC甚至有一个公式的解决方案,因此运行时间为O(1),几乎是即时的)。

因此对于某些事情来说,递归函数比迭代更容易编写,有时反过来。但是通过使用递归函数,您必须注意运行时!