1. 程式人生 > >程式設計師面試一百題-08-求1+2+...+n

程式設計師面試一百題-08-求1+2+...+n

1-題目 :
求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字以及條件判斷語句(A?B:C)。

2-思路 :
這道題沒有多少實際意義,因為在軟體開發過程中沒有這麼多限制,但是可以很好的發散思維。通常除了用公式n(n+1)/2之外,無外乎迴圈和遞迴兩種思路。
由於已經明確限制for和while的使用,迴圈已經不能再用了。同樣,遞迴函式也需要用if語句或者條件判斷語句來判斷是繼續遞迴下去還是終止遞迴,但現在題目已經不允許使用這兩種語句了。
2.1-仍然圍繞迴圈做文章。迴圈只是讓相同的程式碼執行n遍而已,我們完全可以不用for和while達到這個效果。比如定義一個類,我們new一含有n個這種型別元素的陣列,那麼該類的建構函式

將確定會被呼叫n次,可以將需要執行的程式碼放到建構函式裡。
2.2-同樣也可以圍繞遞迴做文章。既然不能判斷是不是應該終止遞迴,我們不妨定義兩個函式。一個函式充當遞迴函式的角色,另一個函式處理終止遞迴的情況,我們需要做的就是在兩個函式裡二選一。從二選一我們很自然的想到布林變數,比如true時呼叫第一個函式,false時呼叫第二個函式。那現在的問題是如和把數值變數n轉換成布林值,如果對n連續做兩次反運算,即!!n,那麼非零的n轉換為true,0轉換為false。

3-程式碼 :
3.1-思路1程式碼 :

class C1
{
  private:
    static int n;
    static int sum;

  public:
    //建構函式
    C1()
    {
        ++n;
        sum += n;
    }
    //重置函式
    static void Reset()
    {
        n = 0;
        sum = 0;
    }
    //獲取和
    static int GetSum()
    {
        return sum;
    }
};

int C1::n = 0;
int C1::sum = 0;

int SolutionSum1(int n)
{
    C1::Reset();
    C1 *a = new C1[n];
    delete[] a;
    a = 0;
    return C1::GetSum();
}

3.2-思路2程式碼 :

//A->Sum函式的作用:當n=0時,停止遞迴
class A
{
  public:
    virtual int Sum(int n)
    {
        return 0;
    }
};

//B->Sum函式的作用:當n!=0時,繼續遞迴
class B : public A
{
  public:
    virtual int Sum(int n)
    {
        return Arr[!!n]->Sum(n - 1) + n;
    }
};

//用虛擬函式來實現函式的選擇(虛擬函式可以實現多型性)
//當n不為零時,執行函式B::Sum;當n為0時,執行A::Sum
int SolutionSum2(int n)
{
    A a;
    B b;
    //定義一個A類的陣列
    A *Arr[2];
    Arr[0] = &a;
    Arr[1] = &b;

    //假設n不為0
    int res = Arr[1]->Sum(n);
    return res;
}