美文网首页
递归算法

递归算法

作者: dlihasa | 来源:发表于2018-09-25 23:09 被阅读50次

我们先用递归算法来解决一个小问题,当然这个小问题不必用算法来解,只是为了对递归做个说明。

问题:在一个数组中找出最大的数。

递归算法解决如下:

public class Recursion {

    public static void main(String[] args) {
        int[] arr = {3,1,4,6,9,8,10,23,14};
        System.out.println(getMax(arr,0,arr.length-1));
    }
    
    public static int getMax(int[] arr,int L,int R){
        if(L == R){
            return arr[L];
        }
        int mid = (L + R)/2;
        int maxLeft = getMax(arr,L,mid);
        int maxRight = getMax(arr,mid+1,R);
        return Math.max(maxLeft, maxRight);
    }

}

运行结果如下:

23

栗子中,把目标数组分成左右两组的思路将大问题分成子问题,不断地按照分成两组的思路继续下分,最终有一个if的条件语句作为递归的条件终结。上述就是递归的两个关键点:大问题划分为子问题、最终有一个条件结束递归。

那么递归的内部执行到底是什么呢?其实方法调用都存在压栈出栈的问题,假如数组为{4,1,2,3},
【A】首次执行,L=0,R=3,L不等于R,mid为(0+3)/2=1,执行到maxLeft这行代码,此时需要执行子方法getMax()(递归中就是自身),那么此时会做一个方法压栈(就是将此时方法执行到哪一行、一些变量如mid是多少,L是几,R是几这些所有有关信息保存到方法栈中,L=0,R=3,mid=1,执行到x行)。
【B】这些做好之后就会执行该子方法getMax,L=0,R=1,L不等于R,mid为(0+1)/2=0,再次执行到maxLeft这行代码,重复上述过程,方法压栈(L=0,R=1,mid=0,执行到x行)。
【C】这些做好之后就会执行子方法getMax,L=0,R=0,L等于R,return arr[0],返回4。
然后将B出栈,还原现场,继续执行下边的流程

下面我们通过断点来直观地观察一下这个执行过程,数组采用{3,2,4,5}这样一个小数组来方便查看过程(上面图片依次为代码执行到的位置、方法栈、此时方法内各变量的值):
  • 第一轮


    首次执行代码部分.png
    首次进入getMax,方法栈情况.png
    此时方法内各变量的值.png
  • 第二轮


    第二次进入getMax,并执行到了getMax这个位置.png
    将上次执行到的getMax压栈,并再次执行到16行.png
    此时的各变量值.png
  • 第三轮


    此次if条件成立,代码执行到12行.png
    第三次getMax压栈if条件成立.png
    此时变量.png
  • 第四轮


    条件满足跳出getMax,回到调用处.png
    将执行完的getMax方法出栈.png
    还原现场(将出栈方法压栈时保存的信息还原).png

到第四轮有出栈的情况了,出栈完成之后,就会顺着上次执行到的位置往下执行,因为本次递归调用结束了,需要将本次下方的代码继续执行,执行完下方代码之后才算是执行了本次流程,然后才能返回到上次调用的位置继续执行。

整体的执行过程不再一一截图了,写一份代码debug看一下这三张图展示的信息细细想来也就理解了。

递归方法的时间复杂度比较复杂

归纳一个表达式(master公式):T(N)=aT(N/b)+O(N^d)
栗子中套入上述表达式为2T(N/2)+O(1)

剖析递归行为和递归行为时间复杂度的估算

master公式T(N)=aT(N/b)+O(N^d)
1、log(b,a)>d ——> 复杂度为O(N^log(b,a))
2、log(b,a)=d ——> 复杂度为O(N^d*logN)
3、log(b,a)<d ——> 复杂度为O(N^d)

所有的递归都可改为非递归,无非就是系统帮我们压栈改为我们自己压栈。

注:还有另外一个表达式不在阐述。大部分都可以用上述表达式计算。

相关文章

  • 快速幂模板

    递归算法 非递归算法

  • python递归算法、尾递归算法及优化

    文章概述 递归算法和尾递归概述递归算法的优化 递归算法 介绍:递归算法是计算机编程领域非常重要的一种算法,采用分而...

  • C++ 递归算法

    递归算法,尾递归算法求阶乘!

  • Java递归算法详解

    递归算法是一种直接或者间接调用自身函数或者方法的算法。Java递归算法是基于Java语言实现的递归算法。递归算法的...

  • 矩阵链乘法

    递归算法: 迭代算法: 分析 递归算法:规模为n的问题,有n个递归,每个递归又有相应矩阵个数个递归,故T(n)=T...

  • 【Python】(十一)从汉诺塔看Python中的递归问题

    递归的原则 递归算法必须具有基本情况。 递归算法必须改变其状态并向基本情况靠近。 递归算法必须以递归方式调用自身 ...

  • 一、算法

    目标 递归算法查找算法算法分析十大排序算法 递归算法 什么是递归递归,在数学与计算机科学中,是指在函数的定义中使用...

  • 欧几里得算法

    非递归算法 默认输入 m>=n 递归算法

  • 递归、回溯、分治

    递归 (1)子集 方式一:递归算法 方式二:位运算算法 (2)子集II 方法一:递归算法 方法二:位运算 (3)组...

  • 二叉树三种遍历的实现(递归)

    前序递归遍历算法:访问根结点-->递归遍历根结点的左子树-->递归遍历根结点的右子树 中序递归遍历算法:递归遍历根...

网友评论

      本文标题:递归算法

      本文链接:https://www.haomeiwen.com/subject/iedroftx.html