递归 - 试图理解

时间:2012-01-06 10:21:29

标签: 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];
  else
    return result;

}

我已经完成了这项工作,并且从我看到该方法的教程开始经过一些时间,我总是忘记了递归的想法。我想如果有人会解释我这个方法的每一步 - 我会一劳永逸地得到这个想法。

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

运行此方法时,这里的步骤是什么?结果的价值是什么,(a,length-1)的作用是什么? (我已经尝试过调试器,但它没有帮助我)

4 个答案:

答案 0 :(得分:5)

让我看看我是否可以阐明这个问题。

在考虑递归时,它(至少我)有助于以更具声明性的方式思考程序,这意味着,您想到了您要完成的任务,而不是考虑所需算法的每个步骤完成它。

让我们检查你的例子,你需要找到一个数组中的最大值,所以我们将在较小的问题中解决这个问题。

如果Array的大小为1,则只有一个元素......因此一个是最大值。容易。

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

这就是你在其余代码中所做的事情。您将算法应用于从位置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})是

max(1,1)  = 1

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

max(1, 0) = 0
max(1, 2) = 2 

所以结果将是2。

答案 1 :(得分:3)

我会尝试逐步解释:

首先,使用参数{1,1,0,2}和4

调用方法

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

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

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

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

完成

答案 2 :(得分:2)

  

结果的价值是什么

这就是递归的重点:结果没有一个值,这可能让你感到困惑。结果的值依次为1,1,1和2。

  

运行此方法时的步骤是什么?

以下是发生的事情:

What is the max of: {1} ?  Result is: 1   
What is the max of: {(1), 1} ?  Result is: 1
What is the max of: {(1, 1), 0} ?  Result is: 1
What is the max of: {(1, 1, 0), 2} ?  Result is: 2

请注意,在使用递归方法时,调试确实不是那么简单。它有时可以帮助打印方法调用“缩进”到深度递归级别,就像我在这里回答的这个问题:

How do I solve the 'classic' knapsack algorithm recursively?

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

  

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

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

这是一个链接,显示如何在不同语言的 lot 中查找列表的最大值。其中一些,如OCaml,以功能形式表达:

http://rosettacode.org/wiki/Greatest_element_of_a_list

三行OCaml(来源:维基百科):

let my_max = function
    [] -> invalid_arg "empty list"
  | x::xs -> List.fold_left max x xs

答案 3 :(得分:1)

这个想法基本上就是你只需稍微更改一下输入数据即可再次完成同样的工作。

代码本身很简单:

  • 第一次if检查递归结束
  • int result行执行递归
  • 最后你会找到最大元素并将其返回。