【Data Structure & Algorithm】求1+2+…+n
求1+2+…+n
题目:求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次。可以将需要执行的代码放到构造函数里。如下代码正是基于这个思路:
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。有了上述分析,代码如下:
class A;
A* Array[2]; class A
{
public:
virtual int Sum(int n){ return 0; }
}; class B : class 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();也可以直接调用函数指针数组,这样可能还更直接些:
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);
}
另外还可以让编译器来完成类似递归的运算,代码如下:
template<int n> struct solution4_Sum
{
enum Value{ N = solution4_Sum<n-1>:: N+n };
};
template<> structsolution4_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不能太大。
【Data Structure & Algorithm】求1+2+…+n的更多相关文章
- 【Data Structure & Algorithm】求子数组的最大和
求子数组的最大和 题目:输入一个整型数组,数组里有正数和负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值,要求时间复杂度为O(n).例如输入数组为1, - ...
- [Data Structure & Algorithm] Hash那点事儿
哈希表(Hash Table)是一种特殊的数据结构,它最大的特点就是可以快速实现查找.插入和删除.因为它独有的特点,Hash表经常被用来解决大数据问题,也因此被广大的程序员所青睐.为了能够更加灵活地使 ...
- [Data Structure & Algorithm] 七大查找算法
查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算,例如编译程序中符号表的查找.本文简单概括性的介绍了常见的七种查找算法,说是七种,其实二分查找.插值查找以及斐波那契查找 ...
- 【Data Structure & Algorithm】字符串全排列
字符串全排列 题目:输入一个字符串,打印出该字符串的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab.cba. 分析:考察对递归的理 ...
- 【Data Structure & Algorithm】在排序数组中查找和为定值的两个数
在排序数组中查找和为定值的两个数 题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字,要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出 ...
- 【Data Structure & Algorithm】 查找最小的k个元素
查找最小的k个元素 题目:输入n个整数,输出其中最小的k个. 例如输入1, 2, 3, 4, 5, 6, 7和8这八个数字,则最小的4个数字为1, 2, 3和4. 分析:这道题最简单的思路是把输入的n ...
- [Data Structure & Algorithm] 八大排序算法
排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...
- 【Data Structure & Algorithm】二叉树中和为某值的所有路径
二叉树中和为某值的所有路径 题目:输入一个整数和一个二叉树,从树的根节点开始往下访问一直到叶节点所经过的所有节点形成一条路径.打印出和与输入整数相等的所有路径. 例如输入整数22和如下二叉树: 10 ...
- 【Data structure & Algorithm】把二元查找树转变成排序的双向链表
把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表,要求不能创建任何新节点,只调整指针指向. 比如将二元查找树 10 / \ 6 ...
随机推荐
- 实习日记 laravel怎么删除磁盘上的文件
Storage 里面有 delete的方法 具体使用是 Storage::disk('uploads')->delete($fileName); 其中'uploads'是filesystem里面 ...
- Introducing Gradle (Ep 2, Android Studio)
https://www.youtube.com/watch?v=cD7NPxuuXYY Introducing Gradle (Ep 2, Android Studio) https://www ...
- Linux问题,磁盘分区打不开了
Metadata kept in Windows cache, refused to mount. chkdsk /f http://www.bubuko.com/infodetail-1184937 ...
- css3背景及字体渐变
1.背景渐变: .linear { width: 100%; FILTER: progid:DXImageTransform.Microsoft.Gradient(gradientType=0,sta ...
- byte数组和文件的相互转换
/** * 获得指定文件的byte数组 */ private byte[] getBytes(String filePath){ byte[] buffer = null; try { File fi ...
- 自定义 spinner
http://blog.sina.com.cn/s/blog_3e333c4a010151cj.html
- .Net——实现IConfigurationSectionHandler接口定义处理程序处理自定义节点
除了使用.net里面提供的内置处理程序来处理我们的自定义节点外,我们还可以通过多种方法,来自己定义处理类处理我们的自定义节点,本文主要介绍通过实现IConfigurationSectionHandle ...
- html中设置透明遮罩层的兼容性代码
说明:下面遮罩层的height视实际情况自行修改,要求显示的div层的样式需加上position:relative,位于遮罩层层div的下面一行.<div id="ceng" ...
- [Phoenix] 五、二级索引
摘要: 目前HBASE只有基于字典序的主键索引,对于非主键过滤条件的查询都会变成扫全表操作,为了解决这个问题Phoenix引入了二级索引功能.然而此二级索引又有别于传统关系型数据库的二级索引,本文将详 ...
- html5 file 上传图片
说明:开发环境 vs2012 mvc4项目,后台语言csharp 1.前端代码 <html xmlns="http://www.w3.org/1999/xhtml"> ...