[随笔]牛客网 "BC172 牛牛的排列数" 递归实现

48 阅读3分钟

因为本人是一位编程小白,目前也是刚刚才学习到C语言。今天在牛客网做一些练习的时候,遇到了下面的这一道题,想要来记录和分享一些东西。

下面呢是这一题目的描述:

6cc20075e6d0bfb42ed53a85c5ffd61.png

题目分析: 这一题要是使用循环的方式来实现还是比较容易的,但是这道题目出现在“递归专区”,我感觉还是有一点点难度...(这个地方可能是我太菜了)。

思路分析: 因为我们要使用递归实现这个问题,那么就一定要用“大事化小”的思路。计算一个排列数,就可以理解是选择问题,题目中的示例1的意思就是在4个中选择2个。 这个地方,大事化小的思路就可以分析为:

4个里面选择2个,就是4个里面选一个,选完在3个里面选1个。再举一个例子。5个里面选择3个,就是5个里面选择1个,选完之后在4个里面选择2个;而4个里面选择2个就又和前面的第一个示例一样了! 分析到这里我们就可以写一部分代码了:

#include <stdio.h>
int func(int n, int m)
{
    // n 代表从n个数中选择,m 表示从n个数中选择m个数
    return n * func(n - 1, m - 1);
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int ret = func(n, m);
    printf("%d", ret);
    return 0;

那么,我们该如何退出递归呢?继续回到我们的分析里面:我们发现当到 “在3个中选择1个时候,这个时候我们有三种选法,在4个中选择1个的时候我们有4种选法,也就是说当最后一步中,当我们从n个中选择1个的时候,我们就n种选法,这样我们就可以退出递归了” ,所以我们就可以补充我们的代码了。

#include <stdio.h>
int func(int n, int m)
{
    // 被选择的数等于1的时候,我们就退出递归
    if (m == 1)
        return n;
    else
        return n * func(n - 1, m - 1);
    // 用一个示例来分析一下,当我们从5个中选择3个,第一个n = 5,m = 3进入函数
    // m != 1, 进入else 5 * func(4, 2)
    // 第二次 n = 4, m = 2 进入函数
    // m != 1, 进入else 4 * func(3, 1)
    // 第三次 n = 3, m = 1 进入函数
    // 此时 m == 1, 返回 3,退出递归
    // 返回到第二层函数, 此时,第二层函数再返回 4 * 3
    // 退入第一层函数, 此时第一层函数返回 5 * 4 * 3
    // 所以结果就是 60
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int ret = func(n, m);
    printf("%d", ret);
    return 0;
}

50f0ec667e55837c47a4c7d6ec15cb0.png

再验证题目中的计算方法:n! / (n - m)! = 5! / 2! = 60。 验证正确!

此文是我在"稀土掘金"的第一篇随笔,也算是一篇小文章了,我会在"掘金"持续分享一些我自己的随笔和想法,和大家共同进步!也希望可以在"掘金"中认识一些大佬,在计算机方向中学习到更多技术!