【剑指offer之求1+2+...+n】九度OJ-1506-求1+2+3+...+n

来源:互联网 发布:中囯邮政网络培训学院 编辑:程序博客网 时间:2024/05/20 23:38

【题目链接】:九度OJ-1506-求1+2+3+…+n
【题目描述】:
题目 1506:求1+2+3+…+n
时间限制:1 秒内存限制:128 兆特殊判题:否提交:1857解决:1060
题目描述:
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
输入:
输入可能包含多个测试样例。
对于每个测试案例,输入为一个整数n(1<= n<=100000)。
输出:
对应每个测试案例,
输出1+2+3+…+n的值。
样例输入:
3
5
样例输出:
6
15
【思路】这道题很考察发散思维,具体参见如下:
这里写图片描述
这里写图片描述
这里给出四钟解法,如果还有其他的欢迎大家补充~
【解法一】利用构造函数求解
我们仍然围绕循环做文章,循环只是让相同的代码重复执行n遍而言,我们完全可以不用for和while来达到这个效果,比如我们先定义一个类型,接着创建n个该类型的实例,那么这个类型的构造函数将确定会被调用n 次。我们可以将与累加相关的代码放到构造函数中,代码如下:

// ====================方法一===================class temp{public:    temp() { ++n; sum += n; }    static void reset() {n=0; sum=0;}    static unsigned int GetSum() {return sum;}private:    static unsigned int n;    static unsigned int sum;};unsigned int temp::n = 0;unsigned int temp::sum = 0;unsigned int sum_solution1(unsigned int n){    temp::reset();    temp *a = new temp[n];    delete []a;    a = NULL;    return temp::GetSum();}

【解法二】利用虚函数求解
我们同样也可以围绕递归做文章。既然不能在一个函数中判断是不是应该终止递归,那么我们不妨定义两个函数:一个函数充当递归函数的角色,另一个函数处理递归的情况,我们需要做的就是在两个函数里二选一。从二选一我们很自然地想到布尔变量,比如值为true{1}的时候调用第一个函数,值为false的时候调用第二个函数,那现在的问题是如何把数值变量n换成布尔值,如果对n连续做两次反运算,即!!n那么非零的n转换为true,0转换为false。有了上述分析,我们再来看下面的代码:

// ====================方法二===================class A;A* array[2];class A{public:    virtual unsigned int sum(unsigned int n)    {        return 0;    }};class B: public A{public:    virtual unsigned int sum(unsigned int n)    {        return array[!!n]->sum(n-1)+n;    }};int sum_solution2(int n){    A a;    B b;    array[0]= &a;    array[1]= &b;    int value = array[1]->sum(n);    return value;}

这种思路是用虚函数来实现的选择。当n!=0时调用函数B::sum;否则调用函数A::sum。

【解法三】利用函数指针求解
在纯C语言的编程环境中,我们不能使用函数,此时可以用函数指针来模拟,这样代码可能还更加直观:

// ====================方法三===================typedef unsigned int (*fun)(unsigned int);unsigned int solution3_temp(unsigned int n){    return 0;}unsigned int sum_solution3(unsigned int n){    static fun f[2] = {solution3_temp,sum_solution3};    return n + f[!!n](n-1);}

【解法四】利用模板类型求解
另外我们还可以让编译器帮助完成类似递归的计算代码如下:

// ====================方法四===================template <unsigned int n> struct sum_solution4{    enum value{N = sum_solution4<n-1>::N+n};};template <> struct sum_solution4<1>{    enum value { N = 1};};template <> struct sum_solution4<0>{    enum value { N = 0};};

【说明】:强调内容 sum_solution4<100>::N 就是求1+2+…+100的结果,当编译器看到sum_soution4<100>时,就会为模板类sum_solution4 以参数100生成该类型的代码。但以100为参数的类型需要得到以99为参数的类型,因为sum_solution4<100>::N=sum_solution4<99>::N+100.这个过程会一直到参数为1的类型,由于该类型已经显示定义,编译器无须生成,递归编译到此结束。由于这个过程是在编译过程中完成的,因此要求输入n必须是在编译期间就能确定的常量,不能动态输入,这是该方法最大 确定,而且编译器对递归编译代码的递归深度有限制的,也就是要求n不能太大。

完整测试代码:

/**********************************   Date:2017-04-15 21:40*   Author:herongwei*   Problem: 题目1506:求1+2+3+...+n*   Source:http://ac.jobdu.com/problem.php?pid=1506  【剑指Offer 】*   Result:AC**********************************/#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <set>#include <stack>#include <math.h>#include <map>#include <queue>#include <deque>#include <vector>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 1e5+10;const int maxm = 55;const LL MOD = 999999997;int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};inline int read(){    int  c=0,f=1;    char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}    return c*f;}// ====================方法一===================class temp{public:    temp() { ++n; sum += n; }    static void reset() {n=0; sum=0;}    static unsigned int GetSum() {return sum;}private:    static unsigned int n;    static unsigned int sum;};unsigned int temp::n = 0;unsigned int temp::sum = 0;unsigned int sum_solution1(unsigned int n){    temp::reset();    temp *a = new temp[n];    delete []a;    a = NULL;    return temp::GetSum();}// ====================方法二===================class A;A* array[2];class A{public:    virtual unsigned int sum(unsigned int n)    {        return 0;    }};class B: public A{public:    virtual unsigned int sum(unsigned int n)    {        return array[!!n]->sum(n-1)+n;    }};int sum_solution2(int n){    A a;    B b;    array[0]= &a;    array[1]= &b;    int value = array[1]->sum(n);    return value;}// ====================方法三===================typedef unsigned int (*fun)(unsigned int);unsigned int solution3_temp(unsigned int n){    return 0;}unsigned int sum_solution3(unsigned int n){    static fun f[2] = {solution3_temp,sum_solution3};    return n + f[!!n](n-1);}// ====================方法四===================template <unsigned int n> struct sum_solution4{    enum value{N = sum_solution4<n-1>::N+n};};template <> struct sum_solution4<1>{    enum value { N = 1};};template <> struct sum_solution4<0>{    enum value { N = 0};};// ====================测试代码===================void Test(int n,int expected){    printf("Test for %d begin:\n",n);    if(sum_solution1(n) == expected)        printf("solution1 passed.\n");    else        printf("solution1 failed.\n");    if(sum_solution2(n) == expected)        printf("solution2 passed.\n");    else        printf("solution2 failed.\n");     if(sum_solution3(n) == expected)        printf("solution3 passed.\n");    else        printf("solution3 failed.\n");}void Test1(){    const unsigned int number = 1;    int expected = 1;    Test(number, expected);    if(sum_solution4<number>::N == expected)        printf("solution4 passed.\n");    else        printf("solution4 failed.\n");}void Test2(){    const unsigned int number = 5;    int expected = 15;    Test(number, expected);    if(sum_solution4<number>::N == expected)        printf("solution4 passed.\n");    else        printf("solution4 failed.\n");}void Test3(){    const unsigned int number = 10;    int expected = 55;    Test(number, expected);    if(sum_solution4<number>::N == expected)        printf("solution4 passed.\n");    else        printf("solution4 failed.\n");}void Test4(){    const unsigned int number = 0;    int expected = 0;    Test(number, expected);    if(sum_solution4<number>::N == expected)        printf("solution4 passed.\n");    else        printf("solution4 failed.\n");}int main(){    //freopen("in.txt","r",stdin);    Test1();    Test2();    Test3();    Test4();    return 0;}/* /////////////solution/////////////////Test for 1 begin:solution1 passed.solution2 passed.solution3 passed.solution4 passed.Test for 5 begin:solution1 passed.solution2 passed.solution3 passed.solution4 passed.Test for 10 begin:solution1 passed.solution2 passed.solution3 passed.solution4 passed.Test for 0 begin:solution1 passed.solution2 passed.solution3 passed.solution4 passed./////////////solution////////////////*/
1 0
原创粉丝点击