java - 理解双重递归

标签 java algorithm recursion divide-and-conquer

如果一个函数中只有一个递归调用,我就能很容易地理解递归。但是,当我在同一个函数中看到两个或多个递归调用时,我真的很困惑。示例:

int MaximumElement(int array[], int index, int n)
    {  
        int maxval1, maxval2; 
        if ( n==1 ) return array[index];
        maxval1 = MaximumElement(array, index, n/2); 
        maxval2 = MaximumElement(array, index+(n/2), n-(n/2));
        if (maxval1 > maxval2)
            return maxval1;
        else
            return maxval2;
    }

我理解一件事,即在每次递归调用期间 n 会减半。我只是不明白下一个递归调用是如何工作的。它变得困惑和我的理解,直到那一点分崩离析,我放弃了。如果有人可以用一个简洁的例子手动说明这一点,我将非常感激。我已经完成了编程,并打印了输出。但是,我不明白这背后的计算是如何工作的。这是我的理解,直到一切都变得一无所有:

int a[] = {1,2,10,15,16,4,8}

初始调用:MaximumElement(a, 0, 7)

函数开始: 第一次调用:MaximumElement(a, 0, 7/2) n 现在变成 7/2 = 3

第二次调用:MaximumElement(2,0,3/2) n 现在变成 3/2 = 1

基本条件满足,max1得到a[0] = 1

这里是一切乱七八糟的地方: 第二次递归调用从索引 0 开始,n = 索引 + n/2 = 0 + 1/2 = 0?当我打印值时,程序显示 3 作为第二次调用时 n 的值。

我已经进行了大量编程,但我真的为此做了一场噩梦。非常感谢有人能帮我解决这个问题!!

那是上面的伪代码,但是请看下面我写的 java 代码(如果你想运行它可能会让你更容易):

        public int MAXIMUMELEMENT(int a[], int i, int n)
        {
        int max1, max2;

        System.out.println("1: " + i + " 2: " + n);

        if(n == 1)
        {
            System.out.println("Returning " + a[i]);
        return a[i];
        }



        max1 = MAXIMUMELEMENT(a, i, n/2);

        System.out.println("Index: "+i+" "+" Variable: "+max1+" n value: "+n);


            max2 = MAXIMUMELEMENT(a, i + (n/2), n - (n/2));

        System.out.println("Index2: " + i + " " + "Variable2: " + max2);


        if(max1 > max2)
        {
            System.out.println("Returning.... " + max1 );    
                return max1;
        }
        else
        {
        System.out.println("Returning.... " + max2);     
        return max2;
        }
}

最佳答案

听起来您已经了解基本情况并且知道递归是如何工作的,因此理解您的特定示例的关键是注意给定初始数组

a = [1,2,10,15,16,4,8]

你在“顶层”计算两件事:

maxval1 = MaximumElement(array, 0, 3); 
maxval2 = MaximumElement(array, 3, 4);

  • 使 maxval1 成为数组中从索引 0 开始且大小为 3 的范围内的最大值
  • 使 maxval2 成为大小为 4 的索引 3 范围内数组的最大值

所以

  • maxval1 确实是 10
  • maxval2 确实是 16

你的答案是 16。

递归的好处是您不必担心跟踪范围太广。如果您相信您的基本案例以及您获得基本案例的方式,那么了解一个级别就足够了。

我认为您卡在了您所说的“一切都乱套了”的地方,因为第二个递归调用从起始索引 0 开始。事实并非如此。它从索引 3 开始。(也就是说,假设您的第二个递归调用是计算 maxVal2 的调用)。

这里是您的计算结果的一些缩略图。我冒昧地将您的函数重命名为 m 并假设 maxVal1maxVal2 的计算更加“功能性”。

a = [1,2,10,15,16,4,8]

m(a, 0, 7)
= m(m(a, 0, 3), m(a, 3, 4))
= m(m(m(a, 0, 1), m(a, 1, 2)), m(a, 3, 4))
= m(m(a[0], m(a, 1, 2)), m(a, 3, 4))
= m(m(1, m(a, 1, 2)), m(a, 3, 4))
= m(m(1, m(m(a, 1, 1), m(a, 2, 1)), m(a, 3, 4))
= m(m(1, m(a[1], a[2])), m(a, 3, 4))
= m(m(1, m(2, 10)), m(a, 3, 4))
= m(m(1, 10), m(a, 3, 4))
= m(10, m(a, 3, 4))
= …
= 16

关于java - 理解双重递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19217565/

相关文章:

performance - 在 3 个数组中搜索公共(public)数的复杂性

c++ - 递归算法对数组中每个值小于 x 的元素求和

java - Stream.count() 是否保证访问每个元素?

java - @scope - spring - 使用注释设置范围 "prototype",行为类似于单例。我哪里出错了?

java - 带按钮的 GWT PopupPanel

javascript - 碰撞响应问题——矩形内的基本圆

Java Socket 的应用程序随机停止

c++ - C++ 算法/Boost Lib 是否有基数排序?

linux - 如何修改递归文件夹压缩文件

c - 为什么这个递归代码会抛出段错误?