【语言特性】带限制地求1+2+...+n

就是一个利用语言特性的题,四种都是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值