就是一个利用语言特性的题,四种都是C++实现,第三个也可以用纯C实现。
面试题64:带限制地求1+2+…+n
求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
解法一(构造函数)
创建对象数组即可多次调用构造函数,在调用时操作静态成员。
#include<bits/stdc++.h>
using namespace std;
class Temp {
private:
//两个都是静态变量,所有实例共享
static unsigned int N;//当前要加的数字N
static unsigned int Sum;//数字总和Sum
public:
Temp() {//在构造器里实现N的自增和加到Sum上
++ N;
Sum += N;
}
static void Reset() {//重置
N = 0;
Sum = 0;
}
static unsigned int GetSum() {//获取总和
return Sum;
}
};
//static成员变量需要在类定义体外进行初始化与定义
//因为static数据成员独立该类的任意对象存在
//它是与类关联的对象,不与类对象关联
unsigned int Temp::N = 0;
unsigned int Temp::Sum = 0;
unsigned int Sum_Solution1(unsigned int n) {
Temp::Reset();//重置静态bianl
Temp *a = new Temp[n];//建立n个对象,调用了n次构造器
delete []a;//销毁它们
a = NULL;//避免野指针
return Temp::GetSum();//其中的静态变量已经改变,获取一下
}
int main() {
cout<<Sum_Solution1(5)<<endl;//15
return 0;
}
解法二(虚函数)
使用虚函数建立基类和子类同名的方法,子类递归调用而在n=0时去调用基类对象的该方法,将它们都放在一个数组中,而根据n映射到数组的下标上去。
#include<bits/stdc++.h>
using namespace std;
class A;//类A的声明,因为在定义之前就写了下面这句用A*定义的数组
A* Array[2];//存两个A类型对象指针的数组
class A {//抽象基类A
public:
//A中的Sum将作为递归出口调用的函数
virtual unsigned int Sum (unsigned int n) {
return 0;
}
};
class B: public A {//B类是A类的子类,并override这个Sum函数
public:
//B中的Sum将作为递归调用的Sum
virtual unsigned int Sum (unsigned int n) {
//当n非0时,!!n==true也即1;当n为0时,!!n==false也即0
//所以递归调用到最后n=0时将调用Array[0]的Sum方法
return Array[!!n]->Sum(n-1) + n;
//虚函数的主要作用是在派生类与基础之间产生多态性
//主要是这种泛型让两个方法重名,其实也没利用到多态
}
};
int Sum_Solution2(int n) {
A a;
B b;
//将实例地址绑定到数组中
Array[0] = &a;
Array[1] = &b;
//调用B的Sum方法开始
int value = Array[1]->Sum(n);
return value;
}
int main() {
cout<<Sum_Solution2(5)<<endl;//15
return 0;
}
解法三(函数指针)
如果是纯C里面就没有虚函数,可以用函数指针,思路和上一个一样。
#include<bits/stdc++.h>
using namespace std;
//定义函数指针类型,类型名称为fun,该类型所定义的变量将是函数指针
//并且其所指向的函数是,返回值为unsigned int,形参表为(unsigned int)
typedef unsigned int (*fun)(unsigned int);
unsigned int Solution3_Teminator(unsigned int n) {//递归出口的函数
return 0;
}
unsigned int Sum_Solution3(unsigned int n) {//递归函数
//定义fun类型的函数指针数组f,里面存了这两个函数的函数指针
static fun f[2] = {Solution3_Teminator, Sum_Solution3};
return n + f[!!n](n - 1);//和第二种解法一样的做法
}
int main() {
cout<<Sum_Solution3(5)<<endl;//15
return 0;
}
解法四(递归编译)
利用模板类型递归编译,计算Sum_Solution4<5>::N
需要Sum_Solution4<4>::N
,一直这样递归下去,直到超出编译代码的递归深度限制或者找到了有定义的Sum_Solution4<1>::N
为止。
因为是递归编译时期计算,所以要求n时编译期就能确定的量,不能是变量了。
#include<bits/stdc++.h>
using namespace std;
//当输入具体的n时,Sum_Solution4<n>::N如果没有定义
//则编译需要的这个枚举量N = Sum_Solution4<n - 1>::N + n自然会递归编译
template<unsigned int n> struct Sum_Solution4 {
enum Value { N = Sum_Solution4<n - 1>::N + n};//直到n-1为1时会直接找到下面的Sum_Solution4<1>
};
template<> struct Sum_Solution4<1> {//编译器递归的出口
//enum 枚举类型名 {枚举表};
enum Value { N = 1};
};
//书上没有这个,如果求Sum_Solution4<0>就得不到
//所以单独定义这个特殊值
template<> struct Sum_Solution4<0> {
enum Value { N = 0};
};
int main() {
//取其中的枚举量N
cout<<Sum_Solution4<5>::N<<endl;//15
return 0;
}