1. 程式人生 > >探索一道面試題的多個解法:C++11 求從 1 到 10 的階乘相加的結果

探索一道面試題的多個解法: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:)