提升性能的奥秘:C语言中两种不同算法解决阶乘求和问题

63 阅读2分钟

(一)题目描述

image.png

(二)解法一

分析:为了完成阶乘的求和,我们首先需要产生阶乘数,**那我们如何产生阶乘数( 即n! )呢?**一个for循环即可:

int main()
{
    int n =0;
    scanf("%d",&n);
    int ret = 0;
    for(i=1;i<=n;i++)
    {
        ret=ret*i;
    }

    return 0;
}

不难看出,循环结束后的ret即为n! 好,现在我们已经产生了n!意味着随着n的变化,将会产生1!,2!,3!。。。。。。 最后将它们累加起来就完成本题的结果。 此处的n就需要从1一直变化到9,**那我们如何产生1~9的数呢?**一个for循环即可:

int main()
{
    int sum=0;
    int n=0;
    for(n=1;n<=9;n++)
    {
        int ret = 0;
        for(i=1;i<=n;i++)//此循环产生阶乘数
        {
            ret=ret*i;
        }
        sum+=ret;//将产生的阶乘数及时相加
    }
    printf("%d ",sum);

    return 0;
}

可以看到,这个解法,用了两层循环,第一层产生n(1~9),第二层求n!时间复杂度为O(n^2),并非是个优秀的解法。我们发现,第二层函数求n时,每次都是从1开始累乘,此处能否可以进行优化呢?

(三)解法二

分析:

由于有 image.png 所以,每次求阶乘数时,并不需要重新从1开始累乘,而是在上一次求的的阶乘数的基础上乘以n即可,这样一来,就可以将第二层for循环去掉了。

int main()
{
    int sum=0;
    int n=0;
    int ret = 0;//为了保留上一次的ret值,因此将ret的定义放到了循环外
    for(n=1;n<=9;n++)
    {
        
        ret=ret*n;
        sum+=ret;//将产生的阶乘数及时相加
    }
    printf("%d ",sum);

    return 0;
}

不难发现,此算法下,循环只有一层,时间复杂度为O(n)。运行结果如下: image.png