探索一道面试题的多个解法: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:)
上一篇: JS——质数判断