要理解递归,得先理解递归--用Java语言由浅入深讲解汉诺塔游戏
2019独角兽企业重金招聘Python工程师标准>>>
一、递归是什么?
定义:程序调用自身的编程技巧称为递归。它分为调用阶段和回退阶段,递归的回退顺序是它调用顺序的逆序。
递归使用的是选择结构:if/switch。而for,while,do while使用的是循环结构。
定义不明白不要紧,先思考以下表达式,要怎么写程序来计算呢?
1+2+3....+100=?
很多人第一反应使用for循环来解决:
int sum =0;for (int i = 1; i <= 100; i++) {sum+=i;}System.out.println(sum);//5050
或者二逼青年使用最简洁而且高效的公式(推荐使用,开销最小,且一步到位):
int start =1;int end = 100;int sum =(start+end)*end/2;//首项加末项乘以项数除以二System.out.println(sum);//5050
而递归代码如下:
static int recursion(int n){if(n==1){//递归出口return 1;}else{return n+recursion(n-1);}}
通过初体验对比,不难发现以下递归有以下几个要点:
1.优点:使程序结构更清晰,更简洁,更容易让人理解,
2.缺点:使用递归调用时,如果过多的调用容易造成java.lang.StackOverflowError即栈溢出和程序执行过慢。这是一个潜在Bug和影响程序执行效率问题,需要谨慎使用。对于互联网这种以速度和效率来维护用户量,不得以用递归时,可以把处理的数据放入缓存,或者直接使用迭代等方式来解决。
3.规律:递归要有出口,不然成了死循环。解出递归的要点在于求出n-1,求出了n-1才能求解出n,这是为什么呢?
二、递归的执行过程
前文对于递归的定义中说,递归分为调用阶段和回退阶段,递归的回退顺序是它调用顺序的逆序。为了理解执行过程,这里配合实例讲解。请思考如何写出它的递归代码:
n!=n*(n-1)*(n-2)...*3*2*1
这里给出数学表达式:
从表达式中可以明显的可以看出:1.递归有出口。2.递归是选择结构。递归代码也不难:
它的调用顺序是怎么样的呢?
当你传入5时,方法内会去调用方法factorial(4),然后又调用方法factorial(3)直到factorial(0)=1时开始返回,下面为更详细的图解:
调用阶段
回退阶段
图中红色箭头为调用阶段,绿色箭头为回退阶段。这就是递归的要点在于求出n-1,求出了n-1才能求解出n,它思想其实和数学中的归纳本质上是相同的。
三、汉诺塔游戏讲解
游戏规则:有三根柱子,最左边的一根柱子从下往上按照大小顺序摞着64片圆盘。需要你借助中间的柱子把左边的所有圆盘移动到最右边的柱子上。并且规定,下面圆盘始终要比上面的大,在三根柱子之间一次只能移动一个圆盘。求出最少移动的次数。
如果要把X柱上得3个圆盘移动到Z柱,步骤如下:
①把X柱最上面的小圆盘移动到Z柱。②再把X柱中间大的圆盘移动到Y柱。③把Z柱上最小的圆盘移动到Y柱上。
这三次操作如图所示:
再加上步骤④⑤⑥⑦,所以3个圆盘至少需要移动7次。如果移动6个圆盘时:
所以可以推出,当n个从x柱,经由y柱中转,移动到z柱(解出n层汉诺塔时),有:
当n=0时,
不用做任何操作
当n>0时,
首先,将n-1个盘子从x借助z移动到y
然后,将1个盘子从x移动到z
最后,将在中间y上的n-1个盘子借助x移动到z
为了解出n层汉诺塔,需要先使用n-1层汉诺塔的解法。
从推到过程中我们可以发现:解出递归的要点在于求出n-1,求出了n-1才能求解出n。此外,从数学角度也可以归纳出 0,1,3,7,15,63...表达式为:f(n)=2^n - 1。
现在,我们可以给出代码:
static int t=0;//最少移动次数public static void main(String[] args) {hanio(3,"x","y","z");System.out.println(t);}static void hanio(int n ,String src,String mid,String dest){if(n==1){System.out.println(src+"-->"+dest);//移动过程t++;}else{hanio(n-1,src,dest,mid);//将n-1个盘子从x借助z移动到yhanio(1,src,"",dest);//因为中间柱子没用到,所以可以填""或者填mid,然后将最大的盘子从x直接移动到zhanio(n-1,mid,src,dest);//将在中间y柱上的n-1个盘子借助x移动到z}}
四、总结和展望
递归对于解决某些问题非常方便(比如递归读取文件路径),也易于理解。虽然用迭代不是不可以实现,只是同样为了解决某些特性问题,写出迭代的代码花费的时间和难度却比递归高。
前文提到,递归和数学中的归纳思想本质上是相同的,都是"将复杂的问题简化"。掌握递归思想的核心就在于"把握结构",因为把握结构是分解整个问题的突破口。
转载于:https://my.oschina.net/liughDevelop/blog/1113881
要理解递归,得先理解递归--用Java语言由浅入深讲解汉诺塔游戏相关推荐
- 【使用递归玩通关汉诺塔游戏】算法01-递归(斐波那契数列、汉罗塔问题)-java实现
递归 定义:在一个方法(函数)的内部调用该方法(函数)本身的编程方式 简而言之就是 "自己调自己" 在玩游戏之前让我们先对递归有一个简单的了解吧! 5.1 递归简介 递归必须有一个 ...
- Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏
Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏 目录 输出结果 核心代码 输出结果 核心代码 def hanoi(n,x,y,z):if n==1:print(x,'--→',z) ...
- java实现汉诺塔游戏(递归)(附超详细易懂注释)
我们很容易能想到,可以用递归来实现汉诺塔游戏.因为要将n(n>1)个盘子从"源"柱子移到"目标"柱子,我们要先把n-1个盘子从"源"柱 ...
- C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)
本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...
- c语言递归求塔移动次数,【C语言】Hanoi(汉诺)塔问题,求移动盘子的步骤(递归法)...
所有的循环算法都可以用递归实现,反之不成立,这足以证明递归的重要性! Hanoi(汉诺)塔问题.古代有一个焚塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在上,小的在下,有一 ...
- Python 算法之递归与尾递归,斐波那契数列以及汉诺塔的实现
文章目录 递归概念 递归要素 递归与迭代的区别 示例一:阶乘 示例二:斐波那契数列 示例三:汉诺塔问题 尾递归 Python 中尾递归的解决方案 递归概念 递归:程序调用自身的编程技巧称为递归( re ...
- 递归:这帮小兔子崽子、汉诺塔游戏+习题复习
##坑爹的兔子 ##斐波那契数列的迭代实现 ※我们都知道兔子繁殖能力是惊人的,如下图: ※我们可以用数学函数来定义: ※课间练习:假设 ...
- 汉诺塔递归的空间复杂度_学习算法绕不开的~~汉诺塔
大家好,我是老郝.本文就汉诺塔问题向大家阐述递归的思想. [问题描述] 有三根柱子,最左边的柱子上从大到小放着很多的圆盘,要求把圆盘一个一个的放到最右边的柱子上并且只能小盘子压在大盘子上.(据说古代阿 ...
- 四柱子汉诺塔c语言程序代码,汉诺塔n=4(4个盘)c语言递归编程代码
满意答案 /**************************** 汉诺塔的算法就3个步骤: 第一,把a上的n-1个盘通过c移动到b. 第二,把a上的最下面的盘移到c.a成了空的. 第三,因为n-1 ...
最新文章
- MySQL删除匿名用户,保证登录安全
- 开源项目|从0到1教你搭建一个适配于智能车的目标检测系统
- IOS之仿微信运动项目
- Java开发者薪资最低?程序员只能干到30岁?国外真的没有996?Intellij真的比Eclipse受欢迎?
- iOS 自定义view里实现控制器的跳转
- 特斯拉全自动驾驶硬件发布!马斯克明年推RoboTaxi:傻瓜才用激光雷达
- 【转】PHP的执行原理/执行流程
- extjs中grid中行内文本或图片居中显示
- 电脑关机很慢是怎么回事
- K3S kubernetes-限制节点可启动的pod数量
- 5个CSS3技术实现设计增强
- WordPress主题制作全过程(八):制作index.php
- JetSmartFilters: 如何制作搜索过滤器(1) 使用Jet-Engine
- 屏幕录像专家限制录像时长_屏幕录像档案已更新!
- 如何将XML转换为HL7
- 小米html查看器 联网,小米摄像机如何连接无线路由器通过手机查看
- linux sub减法指令出错,sparc的指令的一些总结
- 《公主连结》交互设计师:如何用TV画手法制作2D技能动画
- Cobbler实现系统自动安装和cobbler的web管理实现
- 利用MySQL实现一个类似美团外卖的外卖订单的数据库管理系统
热门文章
- Android RecyclerView网格布局动画
- Android MultiAutocompleteTextView
- 「ng2」json组装和解析
- Angular5--viewChild/viewChildren、contentChild/contentChildren使用规则小结
- 【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度
- 【读书笔记】100个Switf必备tips
- Lua中调用C/C++函数 (转)
- 容灾技术中的数据一致性保障
- html5之Canvas坐标变换应用-时钟实例
- Leetcode 101.对称二叉树