探索一道面试题的多个解法:C++11 求从 1 到 10 的阶乘相加的结果

一、引言

最近,有个朋友出去面试(才毕业不到一年),里面有一道很简单的笔试题:

请你编写代码,求 1 到 10 的阶乘相加的结果

这是一道非常简单的题目,我们稍微动一动头脑,就能拿出下面的代码:

#include <iostream>
#include <cstdlib>

int factorial(int n)
{
    if (n == 1) return 1;
    return n * factorial(n - 1);
}

int main()
{
    int result = 0;
    for (int i = 1; i <= 10; ++i)
        result += factorial(i);
    std::cout << result << std::endl;
    system("pause");
    return 0;
}

上述代码中,我们首先编写了一个 factorial 函数递归实现对于某个确定数的阶乘计算,然后遍历 1 到 10,得到这十个数的阶乘数之和。

这个方法是很简单,或许就是最优解了。

但是!

人生在于不停的折腾,让我们来看看,如何(凑不要脸,不知道有什么意义 T_T)来使用 C++11 的库函数来实现这个算法。

二、工具一:std::multiplies

这个函数是我在阅读《C++并发编程实战》的时候看到的。

让我们看看标准库里面的解释cppreference

定义于头文件 <functional>
template< class T>
struct multiplies;
template < class T = void>
struct multiplies;
进行乘法的函数对象。等效地在两个 T 类型实例上调用 operator*

根据上述这段话,我们可以很清晰的看到,std::multiplies 就是实现无视类型的 两个 任何类对象实例的乘法的 函数对象

因此,我们可以使用这个函数来进行乘法计算(这一点契合了标准库的算法设计,我下一节会讲到)。

三、工具二:std::accumulate

这个函数也是我在看《C++并发编程实战》的时候看到的 T_T。

那么这个函数有什么强大的地方呢cppreference

定义于 <numeric>
template < class InputIt, class T>
T accumulate( InputIt first, InputIt last, T init);
template < class InputIt, class T, class BinaryOperation>
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
计算给定值 init 与给定范围 [first, last) 中元素的和。第一版用 operator+ 求和元素,第二版本使用二元函数 op(有没有想到刚提到的哪个函数呀 ^_^)

仔细阅读了 std::accumulate 的介绍之后,我们发现,我们可以完成指定范围的数的和。

那么,要完成阶乘相加,我们必然要有乘法计算,这个怎么办呢?

很简单,我们只需要将刚才提到的 std::multiplies 与 std::accumulate 结合起来就可以啦!

现在,两个工具都已经介绍完毕,让我们开始编码吧!

四、我们就是要用牛刀杀鸡学牛刀是怎么用的 T_T

略加思考,我写下了如下的代码:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <functional>
#include <numeric>

int main()
{
    int result = 0;
    std::vector<int> number = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    for (int i = 0; i < number.size(); ++i) {
        int temp = std::accumulate(number.begin(), number.begin() + i + 1, 1, std::multiplies<int>());
        std::cout << number[i] << "'s factorial is " << temp << std::endl;
        result += temp;
    }
    std::cout << result << std::endl;
    system("pause");
    return 0;
}

在这段代码中:

我们首先定义了一个 number 数组,它是我们用 std::accumulate 这个函数的前两个迭代器标记范围时需要的依靠;

然后,我们在 for 循环中,计算一次(也就是一个数)的阶乘之和,乘法使用了 std::multiplies 函数,请注意它的用法;

最后,我们通过 for 循环的遍历,累加,即可得到结果。

当当当!

我们使用了看似更加复杂的代码完成了这个需求~~~

好像有点吃不了撑的 T_T

五、总结

对于这么简单的一道题,却要探索那么“复杂”的解法,其根源在于,去熟悉 C++ 标准库中强大的工具的用法。

从用法中一窥其设计的理念,从杀鸡中得到牛刀的快感。

编程在于乐趣,
To be Stronger:)

猜你喜欢

转载自blog.csdn.net/u012814856/article/details/79836330