看到这个题,不考虑限定条件,我们可能会有两个方向
1.一个就是用等差数列公式m=n(n+1)/2直接就可以求出来了
2.用循环实现
但是上面都限定了。所以我们就要想办法了
我们知道,多数情况下,循环和递归是可以转换的
那么有这样一种最基本方法,我们用递归实现
#include <stdio.h>
#include <iostream>
using namespace std;
int Get_1_add_to_n(int n)
{
if(n==1)
{
return 1;
}
return n+Get_1_add_to_n(n-1);
}
int main()
{
int n=8;
int ret=Get_1_add_to_n(n);
cout<<ret<<endl;
return 0;
}
或者这样:
#include <stdio.h>
#include <iostream>
using namespace std;
class AA
{
public:
AA()
{
_sum=_sum+(++_count);
}
static int _count;//定义静态数据成员
static int _sum;
};
int AA::_count=0;//对静态数据成员进行初始化
int AA::_sum=0;
int main()
{
const int N=10;
AA *p=new AA[N];
cout<<AA::_sum<<endl;
return 0;
}
可是上面的两种方法都不是很优美的解法,因为这样的时间复杂度为O(N),我们是否有一种复杂度为O(1)的解法呢?
我们可以这样想,是否可以将一些操作放在代码编译的时候来做,这样代码运行起来的效率就高了呢。
有人很巧妙的利用到了这一点:
都是别人想的。我只是代码的搬运工:
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
const int N=10;
char arr[N][N+1];
char size=sizeof(arr)/sizeof(arr[0][0]);//N*(N+1)为数组的大小
int ret=size>>1;//完美的利用了N(N+1)/2 cout<<ret<<endl;
return 0;
}
char arr[N][N+1];
char size=sizeof(arr)/sizeof(arr[0][0]);//N*(N+1)为数组的大小
int ret=size>>1;//完美的利用了N(N+1)/2 cout<<ret<<endl;
return 0;
}
但是这种方法是不能运算比较大的数字的,栈上的空间是有限的,可以自己试一下
还有一种方法是这样的:
#include <stdio.h>
#include <iostream>
using namespace std;
template <int N>
class Sum
{
public:
enum//这里是一个匿名枚举类型
{
RET=N+Sum<N-1>::RET,//递归的去计算N+(N-1)+...+1(不过是在编译时进行展开)
};
};
//全特化
template <>
class Sum<1>//N为1时也是上面递归的出口
{
public:
enum
{
RET=1,
};
};
int main()
{
const int N=10;
cout<<Sum<N>::RET<<endl;
//递归的去计算N+(N-1)+...+1(不过是在编译时进行展开)
}
特化的概念是继模板提出来的
前面讲过,模板函数有其重载函数时,这时候就会调用重载函数,不会再去进行推演。
这里模板类中的特化就是不管你调不调用都会生生成代码
template <typename T>
class SeqList
{
public :
SeqList();
~ SeqList();
private :
int _size ;
int _capacity ;
T* _data
};
//必须有一个模板类的基础上才会有特化
template <>//全特化没有模板参数
class SeqList <int>//定义类时显示指定模板参数
{
public :
SeqList(int capacity);
~ SeqList();
private :
int _size ;
int _capacity ;
int* _data ;
};
上面举例的时全特化,还有一种是偏特化
看看下面的例子:
#include <stdio.h>
#include <iostream>
using namespace std;
template<class T1,class T2>
class Data
{
public:
Data()
{
cout<<"<T1,T2>"<<endl;
}
};
//*i*****************************全特化*************************
template<>
class Data<int ,int>
{
public:
Data()
{
cout<<"<int,int>"<<endl;
}
};
//*******************************偏特化**************************
template<class T2>
class Data<char,T2>//对T1进行偏特化
{
public:
Data()
{
cout<<"<char,T2>"<<endl;
}
};
template<class T1>
class Data<T1,char>//对T2进行偏特化
{
public:
Data()
{
cout<<"<T1,char>"<<endl;
}
};
template<class T1,class T2>
class Data<T1 *,T2 *>//对T1和T2进行偏特化,加限制条件
{
public:
Data()
{
cout<<"<*T1,*T2>"<<endl;
}
};
template<class T1,class T2>
class Data<T1 &,T2 &>//对T1和T2进行偏特化,加限制条件
{
public:
Data()
{
cout<<"<int,T2>"<<endl;
}
};
int main()
{
Data<float,float> d0;
Data<int ,int > d1;
Data<int ,char> d2;
Data<char,int> d3;
Data<int *,int *> d4;
Data<int &,int &> d5;
//Data<char,char> d6;
return 0;
}
再结合上面的求1+2+3+...+N,中的模板中的枚举类型在编译时进行展开的例子来理解特化。