递归的使用小结

117 阅读3分钟

递归的三种使用方向:

1.用递归完成递推问题
2.模拟连续发生的动作   
3.进行"自动"的分析

1.用递归完成递推问题

1.将我们的关注点放到要求解的目标上(如斐波那契数)。
2.第n-1次和第n次之间有无关联。(f(n) = f(n-1)+f(n-2))
    如:求阶乘(第n项的阶乘解为:第n-1项的阶乘解*n)、数组求和(前n位的和是前n-1位的和+arr[n])。
3.一定要确定递归的出口
    一般是考虑当n==1或者n==0时。

2.用递归来模拟连续发生的动作

    1.搞清楚连续发生的动作是什么(如汉诺塔的移动)。
            汉诺塔:是将n块铁饼由原始柱子(称之为A)经过中专柱子(称之为B),移动到目标柱子(称之为C)上。
            第一步:将前n-1块铁饼移动到B柱子上,
            第二步:将第n块铁饼移动到C柱子上,
            第三步:将B柱子上的n-1块柱子,通过A柱子移动到C柱子上(一个新的汉诺塔移动问题,n-1块铁饼,原始柱子为B,中转柱子为A,目标柱子为C)
    2.搞清楚不同次的动作之间的区别(即是每次递归调用时,哪一个是原始柱子,哪一个是目标柱子,哪一个是中转柱子)。
    3.递归的出口条件(当只有一个铁饼时,如何解决问题)

3.进行"自动"的分析问题

    1.自动分析的核心一定要改变你的思想。首先你要相信你的递归函数能够解决问题。
    2.再根据这个递归函数将问题代入,思考如何使用递归函数。
    3.递归的出口条件。
        最简单的情况下的问题是如何被解决的。

“自动分析问题”案例:

        放苹果的方法:若有m个苹果,n个盘子。请问针对m,n一共有多少种方法。(顺序不影响,1,2和2,1属于同种方法)
            首先假定我们可以通过函数int count(m,n);解决这个问题
            那么,分析两种可能出现的情况:
                    1.苹果的数量>=盘子的数量(m >= n)
                    2.苹果的数量<盘子的数量(m < n)
                    if(m<n)
                        因为苹果的数量小于盘子的数量,无论如何选择,至少会有一个盘子为空,那么我们将这个盘子移除也不会影响方法的数量。所以count(m,n)=count(m,m);//如果选择空出更多的盘子则由第二种情况判定方法数量。
                    if(m>=n)
                        那么,可能有两种不同的情况,你可以选择每个盘子都至少放一个苹果,也可以选择空一定数量的盘子(空盘子的数目至少为1)。
                             1.有空盘子
                            count(m,n)= count (m,n-1);//去掉多余的盘子
                             2. 没有空盘子
                             没有空盘子时,则至少每一个盘子都会有一个苹果,那么我们先将每一个盘子中的苹果都删除,也不会影响放苹果的方法会重复。再将空的盘子都一处
                             所以count(m,n)=count(m-n,n);现在苹果的数量<盘子的数量了。
            综上:
                    写出以下count函数:
                    int count (m,n)
                    {
                        //递归出口
                        if(m<=1||n<=1)  //当只有一个苹果或只有一个盘子时,只有一种方法
                            return 1;
                        //苹果数小于盘子数
                        if(m<n)
                            return count(m,m);
                        //苹果数大于等于盘子数
                        else
                        {
                            //没有空盘子的方法 + 空盘子的方法
                            return count(m-n,n)+count(m,n-1);
                        }
                    
                    }