简介
递归算法是一种直接或者间接调用自身函数或者方法的算法。说白了就是程序(方法)自己调用自己。
本质
递归算法本质就是将问题的粒度不断缩小,一直缩小到比较小的临界点,然后进行递归调用的过程。
思想
递归算法 从字面意思上看,包含两部分,一部分是递(递归的过程中不断向下传递值),归(值向下传递到一定位置进行回归的一个过程,类似你挖坑,挖到底的宝贝了(临界点),怕被人发现,然后就要把坑填上的过程)。学过栈结构的童鞋,可以想象成递即为压栈的过程,归即为出栈的过程。
递归的模板结构
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;
}
老实讲我也是刚学习递归算法没多久,刚开始学确实比较难理解,就很抽象,无法想象出整个递归的过程。尤其记得当时在看使用递归完成单链表反转这个算法时,看的一脸蒙蔽。最后还是断点跟了好久才能理解。不理解的小伙伴建议还是断点跟几道算法题,看看中间变量值的传递过程。在断点的过程中脑瓜里面要时不时的想想栈的数据结构,配合栈的压栈和出栈过程,应该会更容易理解一点。
关于栈的压栈和出栈操作,大林子找了一个图片,没有基础的童鞋可以先看一下哈