本面試題均轉換何海濤部落格:
題目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字以及條件判斷語句(a?b:c)。
分析:這道題沒有多少實際意義,因為在軟體開發中不會有這麼**的限制。但這道題卻能有效地考查發散思維能力,而發散思維能力能反映出對程式設計相關技術理解的深刻程度。
通常求1+2+…+n除了用公式n(n+1)/2之外,無外乎迴圈和遞迴兩種思路。由於已經明確限制for和while的使用,迴圈已經不能再用了。同樣,遞迴函式也需要用if語句或者條件判斷語句來判斷是繼續遞迴下去還是終止遞迴,但現在題目已經不允許使用這兩種語句了。
我們仍然圍繞迴圈做文章。迴圈只是讓相同的**執行n遍而已,我們完全可以不用for和while達到這個效果。比如定義乙個類,我們new一含有n個這種型別元素的陣列,那麼該類的建構函式將確定會被呼叫n次。我們可以將需要執行的**放到建構函式裡。如下**正是基於這個思路:
class
temp
static
void reset()
static
int getsum()
private
:static
int n;
static
int sum;
};int
temp::n = 0;
inttemp::sum = 0;
intsolution1_sum(int n)
我們同樣也可以圍繞遞迴做文章。既然不能判斷是不是應該終止遞迴,我們不妨定義兩個函式。乙個函式充當遞迴函式的角色,另乙個函式處理終止遞迴的情況,我們需要做的就是在兩個函式裡二選一。從二選一我們很自然的想到布林變數,比如ture(1)的時候呼叫第乙個函式,false(0)的時候呼叫第二個函式。那現在的問題是如和把數值變數n轉換成布林值。如果對n連續做兩次反運算,即!!n,那麼非零的n轉換為true,0轉換為false。有了上述分析,我們再來看下面的**:
class
a;a* array[2];
classa};
class
b: public a
};int
solution2_sum(int n)
這種方法是用虛函式來實現函式的選擇。當n不為零時,執行函式
b::sum
;當n為0時,執行
a::sum
。我們也可以直接用函式指標陣列,這樣可能還更直接一些:
typedef
int (*fun)(int);
intsolution3_f1(int i)
intsolution3_f2(int i)
; return i+f[!!i](i-1);}
另外我們還可以讓編譯器幫我們來完成類似於遞迴的運算,比如如下**:
template
struct solution4_sum;};
template
<> struct solution4_sum<1>;};
solution4_sum<100>::n
就是1+2+...+100的結果。當編譯器看到
solution4_sum<100>
時,就是為模板類
solution4_sum
以引數100生成該型別的**。但以100為引數的型別需要得到以99為引數的型別,因為
solution4_sum<100>::n=solution4_sum<99>::n+100
。這個過程會遞迴一直到引數為1的型別,由於該型別已經顯式定義,編譯器無需生成,遞迴編譯到此結束。由於這個過程是在編譯過程中完成的,因此要求輸入n必須是在編譯期間就能確定,不能動態輸入。這是該方法最大的缺點。而且編譯器對遞迴編譯**的遞迴深度是有限制的,也就是要求n不能太大。
C C 面試題集合 4
問題 給出如下cmystring 的宣告,要求為該型別新增賦值運算子函式。class cmystring 當面試官要求應聘者定義乙個複製運算子函式時,他會關注如下幾點 是否把返回值的型別宣告為該型別的引用,並在函式結束前返回例項自身 即 this 的引用?只有返回乙個引用,才可以允許連續賦值。否則如...
集合面試題
list,set集合與collection有直接的關係而map屬於間接的關係 list的特點 可以儲存重複的資料,有順序 set的特點 不能儲存重複的資料,沒有順序 map的特點 根據鍵值對保持資料,鍵不可以重複,值可以重複沒有順序 arraylist 優點 查詢速度較快,使用新增和刪除功能較慢 l...
面試題 集合
set 無序 儲存單列資料的集合,儲存的資料是無順序的,並且不允許重複,最常用的是hashset list 有序 儲存單列資料的集合,儲存的資料是有順序的,並且值允許重複,最常用的是arraylist map 儲存鍵值對這樣的雙列資料集合,儲存的資料是無序的,它的鍵是不允許重複的,但是值是允許重複的...