浅谈《剑指offer》原题:求1+2+……+n

《剑指offer》上的一道原题,求1+2+……+n,要求不能使用乘除法,for、while、if、else、switch、case等关键字以及条件判断语句(a?b:c)。

第一次看到这道题大约有一年的时间了,在霸笔网易的时候,当时我就晕了。。。心想这是神马东西,后来发现这是原题!!然后后悔自己没看过书了。。。

《剑指offer》上给出了不错的解法,但是这里有个解法更巧妙,虽然技术含量不高,但是可以参考,这就是《程序员面试笔试宝典》中所给出的答案。

解法一:利用宏定义求解

假设n=1000。相信看到答案的你们都会笑了。

#include <stdio.h>
#define L	sum+=(++n);
#define K	L;L;L;L;L;L;L;L;L;L;
#define J	K;K;K;K;K;K;K;K;K;K;
#define H	J;J;J;J;J;J;J;J;J;J;

int main()
{
	int sum = 0;
	int n = 0;
	H;
	printf("%d\n", sum);
	return 0;
}

怎么样!有木有很搞笑。。。。

解法二:利用构造函数

实际上就是利用类里面的静态成员变量,然后通过构造函数去调用。其实对于c++掌握熟练的人来说,也可以很轻松的明白。

#include <stdio.h>
#include <iostream>
using namespace std;
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();
}

int main()
{
	printf("%d\n", Sum_Solution1(1000));
	return 0;
}

解法三:利用虚函数求解

这也利用了多态的性质,特别巧妙。

#include <stdio.h>
#include <iostream>
using namespace std;

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_Solutiion2(int n)
{
	A a;
	B b;
	Array[0] = &a;
	Array[1] = &b;
	int value = Array[1]->Sum(n);
	return value;
}
int main()
{
	printf("%d\n", Sum_Solutiion2(1000));
	return 0;
}

这种思路基于虚函数来实现函数的选择,当n不为0的时候,一直调用的是B::Sum();当n等于0时,调用的就是函数A::Sum()。

解法四:利用函数指针求解

在纯C语言的编程环境中,我们不能使用虚函数,这时候函数指针就可以达到一样的效果了!

#include <stdio.h>

typedef unsigned int (*fun)(unsigned int);

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

unsigned int Sum_Solutiion3(unsigned int n)
{
	static fun f[2] = {Sum_Solutiion3_Teminator, Sum_Solutiion3};
	return n + f[!!n](n-1);
}

int main()
{
	printf("%d\n", Sum_Solutiion3(1000));
	return 0;
}

解法五:利用模板类型来求解

本质都是多态。可惜不是所有编译器都支持,VC++6.0就不支持。。

#include <stdio.h>
#include <iostream>

template <unsigned int n>struct Sum_Solutiion4
{
	enum Value{N = Sum_Solutiion4<N-1>::N + n};
};

template <> struct Sum_Solutiion4<1>
{
	enum Value{N = 1};
};

int main()
{
	printf("%d\n", Sum_Solutiion4<1000>::N);
	return 0;
}

感觉这道题这些方法都能理解的话,说明c++水平已经不错了,我当时第一次看见都是云里雾里的!

时间: 2024-10-10 07:30:16

浅谈《剑指offer》原题:求1+2+……+n的相关文章

剑指offer链表题的双指针法总结

本篇博客旨在总结双指针法在剑指offer链表题中的应用 包括删除链表中重复的节点.链表中倒数第k个节点.链表中环的入口节点.反转链表.合并两个排序的链表.两个链表的第一个公共节点. 根据双指针的类型,可以大致分为三种: 第一种是间隔一定距离的双指针法,包括删除链表中重复的节点.链表中倒数第k个节点两题 删除链表中重复的节点 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5

剑指 offer 第一题: 二维数组中的查找

打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣 ?? 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 题目分析 图 1 如果没有头绪的话,很显然使用 暴力解法 是完全可以解决该问题的. 即遍历二维数组中的每一个元素,时间复杂度:O(n^2). 其实到这里我们就可以发现,使用这种暴力解法并没有充分利用题目给出的信息.这

剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具体的计算中,还是要将字符串转化成字符数组来进行计算. 实现两个大数的加法,要考虑到两个问题,两个数的和的位数问题,以及如何处理两个数按位相加产生的进位问题.首先两个整数相加,两个数的和的位数最多比最大的整数的位数多1:这样和的位数就确定了.对于进位问题,我的做法是先进行按位相加,相加操作完成后再按照

剑指offer编程题Java实现——面试题9斐波那契数列

题目:写一个函数,输入n,求斐波那契数列的第n项. 1 package Solution; 2 3 /** 4 * 剑指offer面试题9:斐波那契数列 5 * 题目:写一个函数,输入n,求斐波那契数列的第n项. 6 * 0, n=1 7 * 斐波那契数列定义如下:f(n)= 1, n=2 8 * f(n-1)+f(n-2), n>2 9 * @author GL 10 * 11 */ 12 public class No9Fibonacci { 13 14 public static void

剑指Offer对答如流系列 - 求1+2+…+n

面试题64:求1+2+-+n 题目描述 求1+2+-+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 问题分析 有了那么多限制,剩下的我们可以选择 单目运算符:++和--,双目运算符:+,-,移位运算符<>,关系运算符>,<等 逻辑运算符&&,||,&,|,^,赋值= 既然是一个等差数列,和为(n+1)*n/2 我们之前详细探讨了位运算剑指Offer对答如流系列 - 二进制中 1 的个

剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈

剑指offer面试题7相关题目:用两个队列实现一个栈 解题思路:根据栈的先入后出和队列的先入先出的特点1.在push的时候,把元素向非空的队列内添加2.在pop的时候,把不为空的队列中的size()-1份元素poll出来,添加到另为一个为空的队列中,再把队列中最后的元素poll出来两个队列在栈不为空的情况下始终是有一个为空,另一个不为空的.push添加元素到非空的队列中,pop把非空队列的元素转移到另一个空的队列中,直到剩下最后一个元素,这个元素就是要出栈的元素(最后添加到队列中的元素). 1

剑指offer编程题Java实现——面试题14调整数组顺序使奇数位于偶数之前

题目: 输入一个整数数组,实现一个函数来调整该数组中数组的顺序,使得所有的奇数位于数组的前半部分,偶数位于数组的后半部分. 解题思路:数组中维护两个指针,第一个指针初始化时候指向数组头部,第二个指针初始化时候指向数组尾部,第一个指针指向的数字总是偶数,第二个指针指向的数字总是奇数,如果第一个指针在第二个指针之前,则交换两指针指向的元素. 1 package Solution; 2 3 /** 4 * 剑指offer面试题14:调整数组顺序是奇数位于偶数前面 5 * 题目:输入一个整数数组,实现一

剑指offer编程题Java实现——面试题10二进制中1的个数

题目: 请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数.例如,把9表示成二进制是1001,有2位是1,该函数输出2解法:把整数减一和原来的数做与运算,会把该整数二进制表示中的最低位的1变成0,与运算进行多少次就有多少个1. 1 package Solution; 2 /** 3 * 剑指offer面试题10:二进制中1的个数 4 * 题目:请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数. 5 * 例如,把9表示成二进制是1001,有2位是1,该函数输出2 6 * 解法

剑指offer刷题—二维数组的查找

最近接触到一本书叫做剑指offer,在这里准备在这个2个月左右将这本书刷完,当然,不需要每天多少道什么的,不在多,一天理解一道就好了,希望能成为一种习惯,另外,准备在github上也进行同步分享. 今天第一道题: 面试题3:二位数组中的查找 当我们需要解决一个复杂问题时,一个很有效的方法就是从具体的问题出手,通过分析具体的例子,得到规律. 再一个二维数组中,每一行都要按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排列.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含

剑指offer刷题记录

[TOC] 二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 解题思路:从右上角的元素进行判断,如果大于target说明这一列肯定都不是,所以将列数见一:如果小于target说明可能在下一行是等于target的,所以这一行都不是解,所以将行数加1.这样通过一个循环进行判断即可. class Solution { public: bool Find(int tar