1. 程式人生 > >【劍指offer】實現1+2+3+..+n,要求不使用乘除法、迴圈、判斷條件

【劍指offer】實現1+2+3+..+n,要求不使用乘除法、迴圈、判斷條件

這道題目的實質是考察程式設計師的發散思維能力,發散思維能夠反映出應聘者知識面的寬度,以及對程式設計相關技術理解的深度。

拿到這道題時,首先考慮最簡便的方法當然是利用等差數列求和公式(n+1)n/2,想要得出結果,無外乎迴圈和遞迴兩種,但是題目限制了迴圈,判斷條件都不能使用,使用迴圈時就必須使用迴圈判斷條件,,與條件不符;使用遞迴時,少不了if條件,這就需要考慮其他的一些路徑。

針對這道題目,這裡介紹·四種解法,接下來進行逐一介紹:

第一種:利用建構函式求解

實現的方法是將累加相關程式碼放進建構函式裡,通過構造n個物件實現累加的過程

程式碼如下:

#include<iostream>
#include<stack>
using namespace std;
class Temp
{
public:
	Temp(){ ++N; sum += N; }
	static void reset()
	{
		N = 0;
		sum = 0;
	}
	static int get_sum(){ return sum; }
private:
	static int N;
	static int sum;

};
int Temp::N = 0;
int Temp::sum = 0;
 int AddOne2N(int n)
{
	Temp::reset();
	Temp *a = new Temp[n];
	delete[] a;
	a = NULL;
	return Temp::get_sum();

}

方法二、利用虛擬函式求解

主要思想是:利用遞迴,但是不能使用if判斷,這裡就必須用一個東西來替代這個if判斷,這裡我們定義兩個函式,一個函式充當遞迴函式的角色,另一個函式處理終止遞迴的情況,我們需要做的就是在這兩個函式中二選一,利用bool變數是我們能想到的第一個辦法,非零的轉換成true,零轉換成false,這裡對零使用兩次非運算就可實現。

程式碼如下:

class A;
 A* array[2];
 class A
 {
 public:
	 virtual int sum(int n)
	 {
		 return 0;
	 }
 };
 class B :public A
 {
 public:
	 virtual int sum(int n)
	 {
		 return array[!!n]->sum(n - 1) + n;
	 }

 };
	 int AddOne2N2(int n)
 {
		 A a;
		 B b;
		 array[0] = &a;
		 array[1] = &b;
		 int value = array[1]->sum(n);
		 return value;
	 }

方法三、利用函式指標進行計算

在c語言中,沒有虛擬函式機制,此時可以使用函式指標來模擬實現,其中的主要思想和虛擬函式類似,而且使用函式更加直觀一點,程式碼如下:

typedef  int (*fun)(int);
	 int solotion3_tmp(int n)
	 {
		 return 0;
	 }
	 int AddOne2N3(int n)
	 {
		 static fun f[2] = { solotion3_tmp, AddOne2N3 };
		 return f[!!n](n-1) + n;
	 }

方法四、使用模板型別求解

程式碼如下:

 template<int n>
	 struct Sum_Solotion
	 {
		 enum Value{N = Sum_Solotion<n-1>::N+n};
	 };
	 template<>
	 struct Sum_Solotion<1>
	 {
		 enum Value{N = 1};
	 };

Sum_Solotion<100>::N就是1+2+3+...+n的結果,利用編譯器直接生成以100為引數的程式碼,要想生成以100為引數的程式碼,就需要以99為引數的型別,這樣一直遞迴下去,一直遞迴到以1為引數的型別,這時以1為引數的型別不用編譯器生成,已經顯式給出可以直接使用,遞迴編譯到此結束,這裡的缺點就是模板引數n是靜態的一個數,不能動態給出,只能是一個確定的數值。這就是這種方法的一個缺陷。

到此為止,四種方法均已介紹完畢。

完整程式碼如下:

#include<iostream>
#include<stack>
using namespace std;
class Temp
{
public:
	Temp(){ ++N; sum += N; }
	static void reset()
	{
		N = 0;
		sum = 0;
	}
	static int get_sum(){ return sum; }
private:
	static int N;
	static int sum;

};
int Temp::N = 0;
int Temp::sum = 0;
 int AddOne2N(int n)
{
	Temp::reset();
	Temp *a = new Temp[n];
	delete[] a;
	a = NULL;
	return Temp::get_sum();

}
 class A;
 A* array[2];
 class A
 {
 public:
	 virtual int sum(int n)
	 {
		 return 0;
	 }
 };
 class B :public A
 {
 public:
	 virtual int sum(int n)
	 {
		 return array[!!n]->sum(n - 1) + n;
	 }

 };
	 int AddOne2N2(int n)
 {
		 A a;
		 B b;
		 array[0] = &a;
		 array[1] = &b;
		 int value = array[1]->sum(n);
		 return value;
	 }
	 typedef  int (*fun)(int);
	 int solotion3_tmp(int n)
	 {
		 return 0;
	 }
	 int AddOne2N3(int n)
	 {
		 static fun f[2] = { solotion3_tmp, AddOne2N3 };
		 return f[!!n](n-1) + n;
	 }
	 template<int n>
	 struct Sum_Solotion
	 {
		 enum Value{N = Sum_Solotion<n-1>::N+n};
	 };
	 template<>
	 struct Sum_Solotion<1>
	 {
		 enum Value{N = 1};
	 };
	
int main()
{
	int n = 0;
	//cout << "please input the number you want" << endl;
	//cin >> n;
	cout << "the final number is:>>";
	//cout << AddOne2N(n) << endl;
	//cout << AddOne2N2(n) << endl;
	//cout << AddOne2N3(n) << endl;
	
	cout << Sum_Solotion<1>::N << endl;
	system("pause");
	return 0;
}