题目:求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次。我们可以将需要执行的代码放到构造函数里。如下代码正是基于这个思路:
解法一:利用构造函数
1 class Temp 2 { 3 public: 4 Temp() { ++ N; Sum += N; } 5 6 static void Reset() { N = 0; Sum = 0; } 7 static unsigned int GetSum() { return Sum; } 8 9 private: 10 static unsigned int N; 11 static unsigned int Sum; 12 }; 13 14 unsigned int Temp::N = 0; 15 unsigned int Temp::Sum = 0; 16 17 unsigned int Sum_Solution1(unsigned int n) 18 { 19 Temp::Reset(); 20 21 Temp *a = new Temp[n]; 22 delete []a; 23 a = NULL; 24 25 return Temp::GetSum(); 26 }
我们同样也可以围绕递归做文章。既然不能判断是不是应该终止递归,我们不妨定义两个函数。一个 函数充当递归函数的角色,另一个函数处理终止递归的情况,我们需要做的就是在两个函数里二选一 。从二选一我们很自然的想到布尔变量,比如ture(1)的时候调用第一个函数,false(0)的时候 调用第二个函数。那现在的问题是如和把数值变量n转换成布尔值。如果对n连续做两次反运算, 即!!n,那么非零的n转换为true,0转换为false。
解法二:利用虚函数
1 class A; 2 A* Array[2]; 3 4 class A 5 { 6 public: 7 virtual unsigned int Sum (unsigned int n) 8 { 9 return 0; 10 } 11 }; 12 13 class B: public A 14 { 15 public: 16 virtual unsigned int Sum (unsigned int n) 17 { 18 return Array[!!n]->Sum(n-1) + n; 19 } 20 }; 21 22 int Sum_Solution2(int n) 23 { 24 A a; 25 B b; 26 Array[0] = &a; 27 Array[1] = &b; 28 29 int value = Array[1]->Sum(n); 30 31 return value; 32 }
解法三:利用函数指针求解
1 typedef unsigned int (*fun)(unsigned int); 2 3 unsigned int Solution3_Teminator(unsigned int n) 4 { 5 return 0; 6 } 7 8 unsigned int Sum_Solution3(unsigned int n) 9 { 10 static fun f[2] = {Solution3_Teminator, Sum_Solution3}; //函数指针数组 11 return n + f[!!n](n - 1); 12 }