无法理解这种递归

时间:2014-11-02 16:03:04

标签: java recursion

输入为{4,7,3,6,7},输出为:

[81]
[40, 41]
[21, 19, 22]
[11, 10, 9, 13]
[4, 7, 3, 6, 7]

我有的递归程序如下所示,我已经添加了一些print语句来理解递归:

import java.util.Arrays;

public class triangle_array {
    public static void print(int a[])
    {
        if(a.length==0)
            return;
        int n=a.length;
        int newa[]=new int[n-1];
        for(int i=0;i<n-1;i++)
        {
            newa[i]=a[i]+a[i+1];
        }
         System.out.println("here1") ;
        print(newa);
         System.out.println("here2") ;
        if(newa.length!=0)
        System.out.println(Arrays.toString(newa));
    }

    public static void main(String args[])
    {
        int a[]={4,7,3,6,7};
        print(a);
        System.out.println(Arrays.toString(a));
    }

}

我的输出为:

here1
here1
here1
here1
here1
here2
here2
[81]
here2
[40, 41]
here2
[21, 19, 22]
here2
[11, 10, 9, 13]
[4, 7, 3, 6, 7]

我无法完全理解这种递归, 从上面的here语句中,我理解打印方法首先被递归调用,当条件失败时,它返回到打印之外并转到该行并打印“here2”2次并验证newa的长度为零,直到我理解为止,但在下一次迭代中,对于println语句,newa的长度如何增加以及下面的条件如何变为true?

6 个答案:

答案 0 :(得分:1)

通常,如果在递归方法中有打印,则递归调用之前的所有打印将按递增深度增加的顺序打印,递归调用之后的所有打印将打印在递归调用中。逆序。

public static void demoRecursion( int n, int depth ) {

    if ( n <= 0 ) {
        return;
    }

    System.out.println( "Before recursive call, depth " + depth );

    demoRecursion( n - 1, depth + 1 );

    System.out.println( "After recursive call, depth " + depth );

}

如果您使用demoRecursion( 3, 1 )调用此方法,则会获得:

Before recursive call, depth 1
Before recursive call, depth 2
Before recursive call, depth 3
After recursive call, depth 3
After recursive call, depth 2
After recursive call, depth 1

因此,a的大小并没有增加。只是在深度为1时,你有一个5项数组,深度为2,你有一个4项数组,深度为3,你有3个,依此类推。

因此,由于我在上面演示的反向打印效果,每个深度阵列都在之后打印更深层次的数组,这是更短的。

如果您在递归调用之前打印了数组,那么打印将按递减顺序排列。

答案 1 :(得分:1)

你需要认真思考才能正确理解它。

由于你不明白newa的大小如何减少,我将解释那部分。首先,从print调用main方法。
然后,第一个print开始执行,并创建长度为4的newa并停在print(newa)而第二个print开始 然后,第二个print开始执行,并创建长度为3的newa,并在第三个print(newa)启动时停在print。 然后,第3个print开始执行,并创建长度为2的newa,并在第4个print(newa)开始执行时停在print
然后,第4个print开始执行,并创建长度为1的newa,并在print(newa)开始执行时停在print。 然后,第5个print开始执行,并创建长度为0的newa,并在print(newa)停止,同时第6个print开始执行。
然后,第6个print开始执行,并在return;处停止,此时长度为0。

第五个print继续,长度为0时,不会打印任何内容 第4个print继续并打印newa(长度为1)
第3个print继续并打印newa(长度为2)
第二个print继续并打印newa(长度为3)
第一个print继续并打印newa(长度为4)

最后,main打印整个数组。

答案 2 :(得分:0)

newa的长度不会增加,它总是减少一个。最短的一个首先被打印,因为递归调用是之前打印数组的指令。所以它说“创建新的更短的数组,然后先递归处理它(涉及打印),然后自己打印”。

顺便说一句,这种结构的方式有点奇怪。不是在newa方法的末尾打印print,我认为打印a(没有围绕它的if更有意义,然后你也不需要使用main方法打印。

答案 3 :(得分:0)

您的功能以

开头
if(a.length==0)
        return;

因此,当a为空时,该函数会明确停止,但在这种情况下,当a通过给出0长度a来逐渐减少完成时,它会停止。因此,如果您的原始数组有4个条目,该函数将自行调用3次。 5次入场将拨打4次。等等。并且由于每个调用可能会回想起来,5个条目将调用functin,n给出一个包含4个条目的数组,它将给出3个条目的数组,直到单个条目的数组。

int newa[]=new int[n-1];
for(int i=0;i<n-1;i++)
    {
        newa[i]=a[i]+a[i+1];
    }

这是关键:newa []是小于a的一维(n-1,而na的长度。这就是为什么在每一行上数组大小增加1(最后调用,第一次打印)。这是每次提供较小数组的部分。

for循环只是将a的两个邻居值的总和加上new。

这是它将连续提供的:

[4, 7, 3, 6, 7] 
[4+7, 7+3, 3+6, 6+7] --> [11, 10, 9, 13]
[11+10, 10+9, 9+13] --> [21, 19, 22]
[21+19, 19+22] --> [40, 41]
[40+41] --> [81]

首先显示较小的数组,因为当您调用该函数时,它将调用自身直到可能的最小数组。并且打印的结构使得最后一次调用是第一次打印,因为最后调用的函数将是第一个完成,另一个调用不会完成,直到下面的级别还没有完成。这就是为什么你认为a正在增加,你必须以相反的顺序阅读这些功能。

关于您的打印以进行调试。长期的&#34; here1&#34;是由于您在函数打印输出之前打印它的事实。这就是为什么你在这里得到了很多东西1。然后每个函数调用打印输出。

最后,关于最后一个条件:

 if(newa.length!=0)

当a为[81]时,newa将是长度为0的数组,以确保您不能打印0长度的数组。所以这种情况总是如此,直到最后一级。

请注意,将print(newa);置于该条件下并删除检查a的第一部分并不是一个0长度的数组不会改变函数中的任何内容

答案 4 :(得分:0)

基本上,该方法通过对连续元素求和来重复地使阵列变小。例如:

4, 7, 3, 6, 7
|/ |/ |/ |/
11 10 9  13
|/ |/ |/
21 19 22
|/ |/
40 41
 |/
 81

它的工作方式是在每次调用时,它创建一个新的数组,它是一个尺寸较小的元素,称为newa,每个元素newa [i]根据公式newa [i] = a [i]计算+ A [1 + 1]。显然我们想停止某个时候,我们不想继续递归并获得StackOverFlowException,所以当输入数组为空时我们停止。所以,在伪代码中,整个事情是

print(a):
    if a is empty
        escape from function
    else
       create newa array of length a.length-1
       newa[i] = a[i]+a[i+1] //fill the smaller array
       print(newa) // print the smaller array

答案 5 :(得分:0)

有什么可以帮助你理解的是删除所有println语句,而只是在print方法的最开始只放一个System.out.println(Arrays.toString(newa))。三角形将被反转,这将更有意义。