《剑指offer》第六十四题:求1+2+…+n

// 面试题64:求1+2+…+n
// 题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case
// 等关键字及条件判断语句(A?B:C)。

#include <cstdio>

// ====================方法一====================
// 利用构造函数求解
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];  //创建n个实例, 则构造函数会被调用n次
    delete[] a;
    a = nullptr;

    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)  //充当递归函数
    {
        // !!n 非零值为true 零值为false
        return Array[!!n]->Sum(n - 1) + n;
    }
};

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

    //当n大于0时, 总是执行B中sum, 直到n==0
    int value = Array[1]->Sum(n);

    return value;
}

// ====================方法三====================
// 利用函数指针求解
typedef unsigned int (*fun)(unsigned int);

unsigned int Solution3_Teminator(unsigned int n)
{
    return 0;
}

unsigned int Sum_Solution3(unsigned int n)
{
    //静态成员, 实现方法类似于方法二
    static fun f[2] = { Solution3_Teminator, Sum_Solution3 }; //两个函数

    //当n大于0时调用函数Sum_Solution3
    //当n==0时调用函数Solution3_Teminator
    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 begins:\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(int argc, char* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();

    return 0;
}

测试代码

分析:通过各种方法实现递归操作。

typedef int (*fun)( int );
class Solution {
public:

    static int Solution3_Teminator(int n) { return 0; }

    static int Sum_Solution(int n) {

        static fun f[2] = {Solution3_Teminator, Sum_Solution};
        return n + f[!!n](n - 1);
    }
};

牛客网提交代码

原文地址:https://www.cnblogs.com/ZSY-blog/p/12694308.html

时间: 2024-08-03 11:49:15

《剑指offer》第六十四题:求1+2+…+n的相关文章

《剑指offer》第十四题(剪绳子)

// 面试题:剪绳子 // 题目:给你一根长度为n绳子,请把绳子剪成m段(m.n都是整数,n>1并且m≥1). // 每段的绳子的长度记为k[0].k[1].…….k[m].k[0]*k[1]*…*k[m]可能的最大乘 // 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此 // 时得到最大的乘积18. #include <iostream> #include <cmath> // ====================动态规划=========

《剑指offer》第二十四题(反转链表)

// 面试题24:反转链表 // 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的 // 头结点. #include <iostream> #include "List.h" ListNode* ReverseList(ListNode* pHead) { ListNode* pReversedHead = nullptr;//设置三个节点变量,第一是已经被反转的头节点(原链表尾节点) ListNode* pNode = pHead;//第二个是当前节

《剑指offer》第二十四题:反转链表

// 面试题24:反转链表 // 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的 // 头结点. #include <cstdio> #include "List.h" ListNode* ReverseList(ListNode* pHead) { ListNode* pRevHead = nullptr; ListNode* pNode = pHead; //当前节点 ListNode* pPrev = nullptr; //前一个节点 whil

《剑指offer》第二十二题(链表中倒数第k个结点)

// 面试题22:链表中倒数第k个结点 // 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯, // 本题从1开始计数,即链表的尾结点是倒数第1个结点.例如一个链表有6个结点, // 从头结点开始它们的值依次是1.2.3.4.5.6.这个链表的倒数第3个结点是 // 值为4的结点. //O(n)的解法:维护两个指针,让A走B前头,前K步,A到头,B就是解了,但是这个问题在于程序鲁棒性 #include <iostream> #include "List.h&q

《剑指offer》第十二题:矩阵中的路径

// 面试题12:矩阵中的路径 // 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有 // 字符的路径.路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左.右. // 上.下移动一格.如果一条路径经过了矩阵的某一格,那么该路径不能再次进入 // 该格子.例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字 // 母用下划线标出).但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个 // 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入

《剑指offer》第十五题:二进制中1的个数

// 面试题15:二进制中1的个数 // 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如 // 把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. #include <cstdio> int NumberOf1_Solution1(int n) { //主要思路:逐位与运算 int count = 0; unsigned int flag = 1; while (flag) { if (n & flag) ++count; flag = fl

《剑指offer》第十八题:在O(1)时间删除链表结点

// 面试题18(一):在O(1)时间删除链表结点 // 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该 // 结点. #include <cstdio> #include "List.h" void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted) { if (pListHead == nullptr || pToBeDeleted == nullptr) return; //多个

《剑指offer》第二十二题:链表中倒数第k个结点

// 面试题22:链表中倒数第k个结点 // 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯, // 本题从1开始计数,即链表的尾结点是倒数第1个结点.例如一个链表有6个结点, // 从头结点开始它们的值依次是1.2.3.4.5.6.这个链表的倒数第3个结点是 // 值为4的结点. #include <cstdio> #include "List.h" ListNode* FindKthToTail(ListNode* pListHead, unsi

《剑指offer》第十六题(数值的整数次方)

// 面试题:数值的整数次方 // 题目:实现函数double Power(double base, int exponent),求base的exponent // 次方.不得使用库函数,同时不需要考虑大数问题. #include <iostream> #include <cmath> using namespace std; bool g_InvalidInput = false;//使用全局变量作为错误处理方式 bool equal(double num1, double nu