【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 ...
随机推荐
- python--简易员工信息系统编写
补充内容:eval 将字符串变成变量名locals 看输入的是否是字典中的一个keyfunc.__name____怎么看变量名的数据类型斐波那契数列 li=[1,1] while li[-1]&l ...
- javascript 返回上一页面
<a href="<a href="javascript :history.back(-1)">返回上一页</a>或<a href=& ...
- ETL Automation完整安装方法_(元数据存放在mysql数据库)
安装前介质准备: DBI-1.636.tar.gz DBD-mysql-4.037.tar.gz ETL.tar mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz P ...
- Presenting view controllers on detached view controllers is discouraged
本文转载至 http://www.xuebuyuan.com/2117943.html Presenting view controllers on detached view controllers ...
- 用live555将内网摄像机视频推送到外网服务器,附源码
最近很多人问,如何将内网的摄像机流媒体数据发布到公网,如果用公网与局域网间的端口映射方式太过麻烦,一个摄像机要做一组映射,而且不是每一个局域网都是有固定ip地址,即使外网主机配置好了每一个摄像机的映射 ...
- 无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护
golang/goroutine 和 swoole/coroutine 协程性能测试对比 - Go语言中文网 - Golang中文社区 https://studygolang.com/articles ...
- HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件
HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件.它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的.为了容错,文件的所有数据块都会有副本.每个文件的数据块大小和副本 ...
- ABAP 动态内标排序
动态内表怎样排序动态内表怎样排序 动态内表要排序时,因为不知道内表中的字段名字,所以不能直接用SORT table BY field1 field2... 可以使用下面的方法来实现:SORT tab ...
- objective-c的代码块block
一.block 1.bock是由于^开头,括号里面填写参数类型. 标准代码块: 返回值 (^代码块名称) (参数类型) = ^(参数) {方法体}; 2.我们的块即可以定义在函数内或者对象 ...
- [2017-10-26]Abp系列——DTO入参验证使用方法及经验分享
本系列目录:Abp介绍和经验分享-目录 声明式的入参验证逻辑 声明式入参验证主要使用了System.ComponentModel.DataAnnotations中提供的各种验证参数的Attribute ...