zoukankan      html  css  js  c++  java
  • 8.另类方法求1+2+...+n[AnotherMethodOfCalculateSumN]

    题目】

    求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】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    class Temp
    {
    public:
        Temp()
        {
            ++ N;
            Sum += N;
        }

        
    static void Reset()
        {
            N = 
    0;
            Sum = 
    0;
        }
        
    static int GetSum()
        {
            
    return Sum;
        }

    private:
        
    static int N;
        
    static int Sum;
    };

    int Temp::N = 0;
    int Temp::Sum = 0;

    int solution1_Sum(int n)
    {
        Temp::Reset();

        Temp *a = 
    new Temp[n];
        
    delete []a;
        a = 
    0;

        
    return Temp::GetSum();
    }

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

    【代码2】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    class A;
    A *Array[
    2];

    class A
    {
    public:
        
    virtual int Sum (int n)
        {
            
    return 0;
        }
    };

    class B: public A
    {
    public:
        
    virtual int Sum (int n)
        {
            
    return Array[!!n]->Sum(n - 1) + n;
        }
    };

    int solution2_Sum(int n)
    {
        A a;
        B b;
        Array[
    0] = &a;
        Array[
    1] = &b;

        
    int value = Array[1]->Sum(n);

        
    return value;
    }

    这种方法是用虚函数来实现函数的选择。当n不为零时,执行函数B::Sum;当n为0时,执行A::Sum。我们也可以直接用函数指针数组,这样可能还更直接一些:

    【代码3】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    typedef int (*fun)(int);

    int solution3_f1(int i)
    {
        
    return 0;
    }

    int solution3_f2(int i)
    {
        fun f[
    2] = {solution3_f1, solution3_f2};
        
    return i + f[!!i](i - 1);
    }

    另外我们还可以让编译器帮我们来完成类似于递归的运算,比如如下代码:

    【代码4】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
     
    template <int n> struct solution4_Sum
    {
        
    enum Value { N = solution4_Sum < n - 1 >::N + n};
    };
    template <> struct solution4_Sum<1>
    {
        
    enum Value { N = 1};
    };

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

    【参考】

    http://zhedahht.blog.163.com/blog/static/2541117420072915131422/

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/hellogiser/p/3738481.html
Copyright © 2011-2022 走看看