递归算法简介及入门算法

简介

递归算法是一种直接或者间接调用自身函数或者方法的算法。说白了就是程序(方法)自己调用自己。

本质

递归算法本质就是将问题的粒度不断缩小,一直缩小到比较小的临界点,然后进行递归调用的过程。

思想

递归算法 从字面意思上看,包含两部分,一部分是递(递归的过程中不断向下传递值),归(值向下传递到一定位置进行回归的一个过程,类似你挖坑,挖到底的宝贝了(临界点),怕被人发现,然后就要把坑填上的过程)。学过栈结构的童鞋,可以想象成递即为压栈的过程,归即为出栈的过程。

递归的模板结构

1、首先找到递,及递归调用的临界条件,在此终止递的过程。

2、提取重复逻辑,方便调用。

入门算法

1、N的阶乘

描述:给定一个数字,求依次递减相乘结果。比如 4的阶乘即为 4x3x2x1。

 /**
     * n的阶乘
     */
    public static int f1(int n) {
       //递的临界条件
        if (n == 1) {
            return 1;
        }
        //归时的逻辑 前后两个数字相乘
        return n * f1(n - 1);
    }

2、斐波那契数列

描述: 后一个数等于前面两个数相加的数列,比如 1 1 2 3 5

 /**
     * 斐波那契数列(普通递归)
     *
     * @param n
     * @return
     */
    public static int f2(int n) {
        //临界条件
        if (n == 1 || n == 2) {
            return 1;
        }
       //归的计算逻辑
        return f2(n - 1) + f2(n - 2);
    }



    /**
     * 斐波那契数列(递归优化)
     * 将初始化好的数组传入,做缓存(避免重复的计算)
     * @param n
     * @return
     */
    public static int f21(int n, int[] arr) {
        //临界条件
        if (n == 1 || n == 2) {
            return 1;
        }
       //存在则直接取缓存数据
        if (arr[n] != -1) {
            return arr[n];
        } else {
            //将计算过程中的数据暂存到数组中
            arr[n] = f2(n - 1) + f2(n - 2);
        }
        return arr[n];
    }

3、爬楼梯(青蛙跳)

描述: 给定一个台阶总阶数N,你一次可以上1个台阶,也可以一次上两个台阶。问到达第n阶台阶,一共有多少种方法。


    /**
     * 青蛙跳台阶,可以一个,可以两个 问一共有多少跳法
     *
     * @param n
     * @return
     */
    public static int f3(int n) {
        //已知的临界条件,剩1个台阶时只有1种方法,剩两个台阶时有2种方法 
        if (n <= 2) {
            return n;
        }
       //f3(n - 1)即为一步一个台阶的总方法数 f3(n - 2)为一步两个台阶的方法数,相加即为两种方法总和
        return f3(n - 1) + f3(n - 2);
    }

4、单链表反转

描述:给定一个链表譬如 1->2->3->4 ,求输出为4->3->2->1

 /**
     * 反转链表(非递归)
     *
     * @param head
     */
    public static Node reverseNode(Node head) {
        if (head == null || head.next == null) {
            return head;
        }
        Node cur = head;
        Node pre = null;
        while (cur != null) {
            Node next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }


    /**
     * 链表反转(递归版)
     * 实例数据 1->2->3-4
     *
     * @param head
     * @return
     */
    public static Node f4(Node head) {
        if (head == null || head.next == null) {
            //压栈,第一次返回的是最后一个节点4
            return head;
        }
        //返回的是当前节点的上一个节点,比如当return head为节点4时,此时newList节点为3->4,此时的head为上一层的节点3
        Node newList = f4(head.next);
        //后面对head指针的操作即为对newList节点的操作。
        Node t1 = head.next;
        //第一次完成3->4   到   4-3节点指针的反转,将4指向null,断开之前正向指针
        t1.next = head;
        head.next = null;
        return newList;
    }

老实讲我也是刚学习递归算法没多久,刚开始学确实比较难理解,就很抽象,无法想象出整个递归的过程。尤其记得当时在看使用递归完成单链表反转这个算法时,看的一脸蒙蔽。最后还是断点跟了好久才能理解。不理解的小伙伴建议还是断点跟几道算法题,看看中间变量值的传递过程。在断点的过程中脑瓜里面要时不时的想想栈的数据结构,配合栈的压栈和出栈过程,应该会更容易理解一点。

关于栈的压栈和出栈操作,大林子找了一个图片,没有基础的童鞋可以先看一下哈

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值