写出递归函数也就是要处理好递归的3个主要的点:a)出口条件,即递归“什么时候结束”,这个通常在递归函数的开始就写好;b)如何利用“情况n”变化到“情况n+1”,也就是一般情况——“正在“递归中的情况;c)初始条件,也就是这个递归调用以什么样的初始条件开始
一、汉诺塔
将A中的圆盘移至C柱,小圆盘的只能放在大的上面,大圆盘不能放在小的上面。
思想:可以把问题分解为:把A中前4块移到B中,把A中剩下的一块移到C,再把B中的四块移到C。
而如何把A的前四块移到B,如何把B的四块移到C其实就和如何把A的五块移到C是一样的问题,只是n有所改变。
现在我们思考如何建立这个递归函数。
1.函数的要实现的功能
把A柱上的n块借助B柱移动到C柱
void hannuo(int n,char a,char b,char c){}
2.函数的结束条件
n=0
3.写出整个函数:
void hannuo(int n,char a,char b,char c)
{
if(n>=1){ //回想最开始的思路,写出以下三行代码
hannuo(n-1,a,c,b);//把A的前n-1块借助C柱移动到B柱
printf(“%c-->%c\n",a,c);//把A柱的最后一块移到C柱
hannuo(n-1,b,a,c);//把B柱的n-1块借助A柱移动到C柱
}
二、爬楼梯问题
题目:假设你在走楼梯,每次你都可以选择走一步或者两步。如果楼梯一共有n个台阶,那你爬到最高处一共有多少种不同的方式呢?
现在我们思考如何建立这个递归函数。
1.函数的要实现的功能
输出爬n级台阶有多少种方式
void louti(int n){}
2.函数的结束条件
如果不确定如何写结束条件,可以写n=1时,return 1;n=2时,return 2;(因为这两种情况是可以枚举出来的,而其余的任何情况最终都会经历这两个中的一到两种,以这两个作为结束条件万无一失)
3.写出整个函数:
void louti(int n){
if(n==1) return 1;
if(n==2) return 2; //可以走一次两步可以走两次一步,两种方法。
x1=louti(n-1); // 如果这次走一步,那么有x1种走法
x2=louti(n-2); // 如果这次走两步,那么有x2种走法
return x1+x2; // 一共有x1+x2种走法(如果想不通就假设n=3,就能懂了)
}
三、二叉树创建的递归实现
这里以二叉树的先序创建为例,书写伪代码(具体实现代码还望另找他出)(所谓先、中、后指的是根节点在先还是中还是后)
首先建立结构体
typedef struct BinaryTreeNode //相当于给了根节点存放的数据的空间以及左孩子和右孩子的标识
{
int data;
BinaryTreeNode * leftchild;
BinaryTreeNode * rightchild;
}Node,*NodePoint;
书写递归函数
1.函数要实现的功能
按照根节点、左孩子、右孩子的顺序创建
2.确定输入参数
根节点
3.函数的结束条件
输入为null
4.写出伪代码
void Create(*root){
if(root != null){
root = scanf("%d"); //根节点的数据是什么
Create(root->leftchild); //创建左孩子
Create(root->rightchild); //创建右孩子
}
}
LeetCode递归思想练习:(还会继续更新)
10题(比较难)
22题(难度适中,比较传统的递归)