探索一道面試題的多個解法: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++併發程式設計實戰》的時候看到的。
定義於標頭檔案
<functional>
template< class T>
struct multiplies;
template < class T = void>
struct multiplies;
進行乘法的函式物件。等效地在兩個 T 型別例項上呼叫operator*
根據上述這段話,我們可以很清晰的看到,std::multiplies 就是實現無視型別的 兩個 任何類物件例項的乘法的 函式物件。
因此,我們可以使用這個函式來進行乘法計算(這一點契合了標準庫的演算法設計,我下一節會講到)。
三、工具二:std::accumulate
這個函式也是我在看《C++併發程式設計實戰》的時候看到的 T_T。
定義於
<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:)