【算法笔记】递归(recursive)

最近在研究算法…^^ 算法中最基本的是排序。

排序当中最常见的是快速排序(Quick Sort)。
理解快速排序的代码,那就离不开递归了。
递归以前听过,但是真正去了解和研究是最近为了对算法的了解。

递归感觉很绕?

但是理解其原理的话还是可以接受的,甚至有时候会喜欢这种方式。

递归不像传说中的那么麻烦。弄清楚 基线条件(base case)和 递归条件(recursive case)

绝大多数的递归都是这种结构

function(parameter){
    if 基线条件(base case){ //离开递归的条件,这条件如果不明确,或是满足不了。很容易进入死循环。
        return
    }

    XXXX...XXXX //处理业务逻辑

    if 递归条件(recursive case){ //进入递归的条件
        function(parameter)
    }
}

来看看一个简单的例子吧。详细内容可以看这里
https://pintia.cn/problem-sets/994805260223102976/problems/994805325918486528

卡拉兹(Callatz)猜想:

对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;
如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。
我们假设 n < 1000

输入样例:
3
输出样例:
5

一般情况下我们是直接用while或for循环处理。

#include <stdio.h>

int main()
{
    int step = 0; //记录步数
    int n = 0; 

    scanf("%d", &n); 
    while (n != 1)
    {
        if (n % 2 == 0) //判断是不是偶数
        {
            n = n / 2;
        }
        else
        {
            n = (3 * n + 1) / 2;
        }
        step++; //+步数
    }
    printf("%d\n", step);
    return 0;
}

那用递归如何去写呢?

我们先看看这里的 基线条件(base case)递归条件(recursive case)是什么?

function(parameter){
    if n == 1 //基线条件(base case)
        return
    }

    XXXXX // 这里需要些算法逻辑

    function(parameter){} //递归条件(recursive case)什么时候进入递归呢? 是没满足基线条件
}

只要找到基线条件(base case)递归条件(recursive case)这代码就好写了。
我们看看详细的代码?

#include <stdio.h>

void b1001(int &step, int n) // 这里是step的引用值,不想这么用的话直接上面声明全局变量
{
    if (n == 1 or n == 0) //基线条件(base case)满足这条件就退出
    {
        return;
    }

    if (n % 2 == 0)     //这个if else 是处理算法逻辑
    {
        n = n / 2;
    }
    else
    {
        n = (3 * n + 1) / 2;
    }

    step = step + 1; // 处理算法逻辑后 加步骤数

    b1001(step, n); //递归条件(recursive case)是没满足 基线条件(base case)而进入递归方法
}

int main()
{
    int step, n = 0; //步数
    int n = 0; //接收值

    scanf("%d", &n);
    b1001(step, n);
    printf("%d\n", step);
    return 0;
}

大部分的递归逻辑都不会离开这最基本的模式。
不要一看到递归就害怕。静下心来先找找
基线条件(base case)递归条件(recursive case)
会很容易的看出里面的逻辑的。

超级简单吧? (更复杂的方式会在后面的快速排序,深度搜索等算法里去介绍了…)

还有平时处理公司业务逻辑的时候, 能用循环解决的尽量不要用递归。 大部分场景是可以用循环解决问题的。别把事情搞大..
原因很简单,毕竟大部分的队友会看到递归的代码第一反应是: NND 这是谁写的方法?


欢迎大家的意见和交流

email: li_mingxie@163.com