Java 递归-试图理解

Java 递归-试图理解,java,recursion,Java,Recursion,我有下一种方法: public static int maxFind(int [] a, int length) { if (length == 1){ return a[0]; } // recursively maxFind method on length-1 int result = maxFind(a, length - 1); if (a[length - 1] > result) return a[length - 1];

我有下一种方法:

public static int maxFind(int [] a, int length)
{
  if (length == 1){
          return a[0];
  }

  // recursively maxFind method on length-1
  int result = maxFind(a, length - 1);

  if (a[length - 1] > result)
    return a[length - 1];
  else
    return result;

}
我已经完成了这项工作,从看到该方法的教程开始,我就一直忘记了递归的概念。我想,如果有人能向我解释这个方法的每一步,我会一劳永逸地得到这个想法

示例-我的arr为:{1,1,0,2)


当我们运行这个方法时,这里的步骤是什么?结果的值是什么,以及(a,length-1)的作用是什么?(我已经尝试了调试器,但它对我没有帮助)

基本上,您只需稍微更改输入数据就可以再次执行完全相同的操作

代码本身很简单:

  • 第一个
    if
    检查递归结束
  • int结果
    行执行递归
  • 最后查找最大的元素并返回它

让我看看是否能对这个问题有所启发

当考虑递归时,以一种更具声明性的方式来考虑程序(至少对我来说)是有帮助的,也就是说,你考虑你要完成什么,而不是考虑完成它所需的算法的每一步

让我们检查一下您的示例,您需要在数组中找到最大值,因此我们将在较小的问题中分解此问题

如果数组的大小是1,那么只有一个元素…所以一个元素是最大的。很简单

查找最大值的问题可以描述为:列表中的一个元素与所有其他元素的最大值之间的值越大

这就是您在代码的其余部分所做的。您将算法应用于从位置0到长度1的数组,然后比较返回值

这些调用将创建一个递归树,这意味着,将有几个调用“嵌套”,直到每个调用都以length=1(基本情况)完成,然后,算法将开始重建答案

真正理解递归算法的最好方法是抓起一张纸,模拟程序,在纸上为每次调用编写数组值和“长度”值,然后找出每次调用最终达到基本情况后会发生什么

对于{1,1,0,2},基本上会得到一系列调用,类似于:

max(maxFind({1,1,0}), 2)
其中maxFind({1,1,0})归结为:

max(maxFind({1,1}), 0)
maxFind({1,1})是

然后开始沸腾(与上面的顺序相反):


因此结果将是2。

我将尝试一步一步地解释:

首先,使用参数{1,1,0,2}和4调用该方法

1) max_find([1,1,0,2],4)=>length不是1,因此将使用length=4-1再次调用max_find

2) max_find([1,1,0,2],3)=>length不是1,因此将使用length=3-1再次调用max_find

3) max_find([1,1,0,2],2)=>length不是1,因此将使用length=2-1再次调用max_find

4) max_find([1,1,0,2],1)=>长度为1,因此将返回一个[0],即1

5) 现在,步骤3的代码形式计算步骤4=>a[2-1]的结果不大于1,因此返回1

6) 现在,代码形式步骤2对步骤3=>a[3-1]的结果进行求值,结果不是>1,因此返回1

7) 现在,代码形式步骤1对步骤2的结果求值=>a[4-1]为>1,因此它返回的[4-1]为2

完成

结果的价值是什么

这就是递归的要点:result没有一个值,这可能会让你感到困惑,result的值依次是1,1,1,2

当我们运行这个方法时,这里的步骤是什么

下面是发生的情况:

最大值:{1}是多少?结果是:1
{(1),1}的最大值是多少?结果是:1
{(1,1),0}的最大值是多少?结果是:1
{(1,1,0),2}的最大值是多少?结果是:2
请注意,在使用递归方法时,调试确实不是那么简单。将方法调用“缩进”到深度递归级别有时会帮助更多,就像我在这里回答的这个问题:

(当然,您需要以某种方式跟踪递归调用的“深度”)

(a,length-1)的作用是什么?(我已经尝试过调试器,但是 这对我没有帮助)

调试器可能对您没有帮助,因为该方法使用了一种“技巧”来节省Java内存:基本上,通过指示您不应该解析整个数组来缩短输入。但您仍然递归地将整个数组传递给该方法。这是一种“穷人用少一个元素获得列表的功能性方法”)()

这里有一个链接,展示了如何用多种不同的语言查找列表的最大值。其中一些,如OCaml,以函数形式表示:

OCaml的三行代码(来源:Wikipedia):


为什么调试器没有帮助?我在理解blueJ的调试器时遇到了麻烦。我将尝试eclipse调试器。好的,eclipse调试器完成了这项工作。我怎么忘记了这个选项…eclipse有一个很好的调试器。如果你愿意,你仍然可以用blueJ开发,只需使用eclipse进行调试。谢谢你的详细回答。我已经拿了纸,不需要了是的,但是我把它放在了最后。让我看看我是否错了。最后我们(通过我的数组-1,1,0,2)得到了来自if station if(a[0](=1)>result(=1)…的问题。对吗?那么这个方法怎么记得result的最大值是2?或者我在纸上做的树上错了。对不起英文:)如果我能选择两个正确的答案…你和pcalcao和don都是伟大的。谢谢!!!
max(1,1)  = 1
max(1, 0) = 0
max(1, 2) = 2 
let my_max = function
    [] -> invalid_arg "empty list"
  | x::xs -> List.fold_left max x xs