河内之塔算法

Before getting started, let’s talk about what the Tower of Hanoi problem is. Well, this is a fun puzzle game where the objective is to move an entire stack of disks from the source position to another position. Three simple rules are followed:

在开始之前,让我们先讨论一下河内塔问题。 好吧,这是一个有趣的益智游戏,目标是将整个磁盘堆栈从源位置移动到另一个位置。 遵循三个简单的规则:

  1. Only one disk can be moved at a time.一次只能移动一个磁盘。
  2. Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack. In other words, a disk can only be moved if it is the uppermost disk on a stack.每一步都包括从其中一个堆栈中取出上部磁盘并将其放在另一个堆栈之上。 换句话说,仅当磁盘是堆栈中最上面的磁盘时,才能移动磁盘。
  3. No larger disk may be placed on top of a smaller disk.请勿将较大的磁盘放置在较小的磁盘上。

Now, let’s try to imagine a scenario. Suppose we have a stack of three disks. Our job is to move this stack from source A to destination C. How do we do this?

现在,让我们尝试想象一个场景。 假设我们有一叠三个磁盘。 我们的工作是将堆栈从源A移到目标C。 我们如何做到这一点?

Before we can get there, let’s imagine there is an intermediate point B.

在到达那里之前,让我们假设有一个中间点B。

We can use B as a helper to finish this job. We are now ready to move on. Let’s go through each of the steps:

我们可以用B作为帮手来完成这项工作。 我们现在准备继续前进。 让我们完成每个步骤:

  1. Move the first disk from A to C将第一个磁盘从A移到C
  2. Move the first disk from A to B将第一个磁盘从A移到B
  3. Move the first disk from C to B将第一个磁盘从C移到B
  4. Move the first disk from A to C将第一个磁盘从A移到C
  5. Move the first disk from B to A将第一个磁盘从B移到A
  6. Move the first disk from B to C将第一个磁盘从B移到C
  7. Move the first disk from A to C将第一个磁盘从A移到C

Boom! We have solved our problem.

繁荣! 我们已经解决了我们的问题。

You can see the animated image above for a better understanding.

您可以查看上面的动画图像,以更好地理解。

Now, let’s try to build the algorithm to solve the problem. Wait, we have a new word here: “Algorithm”. What is that? Any idea? No problem, let’s see.

现在,让我们尝试构建算法来解决该问题。 等等,我们在这里有一个新词:“ Algorithm ”。 那是什么? 任何想法? 没问题,让我们看看。

什么是算法? (What is an algorithm?)

An algorithm is one of the most important concepts for a software developer. In fact, I think it’s not only important for software development or programming, but for everyone. Algorithms affect us in our everyday life. Let’s see how.

对于软件开发人员来说,算法是最重要的概念之一。 实际上,我认为这不仅对软件开发或编程很重要,对每个人也很重要。 算法会影响我们的日常生活。 让我们看看如何。

Suppose you work in an office. So every morning you do a series of tasks in a sequence: first you wake up, then you go to the washroom, eat breakfast, get prepared for the office, leave home, then you may take a taxi or bus or start walking towards the office and, after a certain time, you reach your office. You can say all those steps form an algorithm.

假设您在办公室工作。 因此,每天早晨您都需要按顺序执行一系列任务:首先醒来,然后去洗手间,吃早餐,为办公室做准备,离开家,然后您可以乘坐出租车或公共汽车或开始向办公室,一段时间后,您到达办公室。 您可以说所有这些步骤构成一个算法

In simple terms, an algorithm is a set of tasks. I hope you haven’t forgotten those steps we did to move three disk stack from A to C. You can also say that those steps are the algorithm to solve the Tower of Hanoi problem.

简而言之,算法是一组任务。 我希望您不要忘记我们将三个磁盘堆栈从A移到C的那些步骤。您也可以说这些步骤是解决河内塔问题的算法。

In mathematics and computer science, an algorithm is an unambiguous specification of how to solve a class of problems. Algorithms can perform calculation, data processing and automated reasoning tasks. — Wikipedia

在数学和计算机科学中,算法是如何解决一类问题的明确规范。 算法可以执行计算,数据处理和自动推理任务。 — 维基百科

If you take a look at those steps you can see that we were doing the same task multiple times — moving disks from one stack to another. We can call these steps inside steps recursion.

如果查看这些步骤,您会发现我们多次执行相同的任务-将磁盘从一个堆栈移动到另一个堆栈。 我们可以在步骤递归中调用这些步骤。

递归 (Recursion)

Recursion is calling the same action from that action. Just like the above picture.

递归 正在从该动作中调用相同的动作。 就像上面的图片一样。

So there is one rule for doing any recursive work: there must be a condition to stop that action executing. I hope you understand the basics about recursion.

因此,执行任何递归工作有一个规则:必须有一个条件来停止执行该动作。 希望您了解有关递归的基础知识。

Now, let’s try to build a procedure which helps us to solve the Tower of Hanoi problem. We are trying to build the solution using pseudocode. Pseudocode is a method of writing out computer code using the English language.

现在,让我们尝试建立一个过程来帮助我们解决河内塔问题。 我们正在尝试使用伪代码构建解决方案 伪代码是一种使用英语写出计算机代码的方法。

tower(disk, source, intermediate, destination)
{}

This is the skeleton of our solution. We take the total disks number as an argument. Then we need to pass source, intermediate place, and the destination so that we can understand the map which we will use to complete the job.

这是我们解决方案的基础。 我们以总磁盘数作为参数。 然后,我们需要传递来源,中间地点和目的地,以便我们能够理解用于完成工作的地图。

Now we need to find a terminal state. The terminal state is the state where we are not going to call this function anymore.

现在我们需要找到一个终端状态 。 终端状态是我们不再要调用此函数的状态。

IF disk is equal 1

In our case, this would be our terminal state. Because when there will be one disk in our stack then it is easy to just do that final step and after that our task will be done. Don’t worry if it’s not clear to you. When we reach the end, this concept will be clearer.

在我们的情况下,这将是我们的终端状态。 因为当堆栈中只有一个磁盘时,很容易执行最后一步,然后完成我们的任务。 如果您不清楚,请不要担心。 当我们走到尽头时,这个概念将更加清晰。

Alright, we have found our terminal state point where we move our disk to the destination like this:

好了,我们找到了终端状态点,将磁盘移动到目标位置,如下所示:

move disk from source to destination

Now we call our function again by passing these arguments. In that case, we divide the stack of disks in two parts. The largest disk (nth disk) is in one part and all other (n-1) disks are in the second part. There we call the method two times for -(n-1).

现在,我们通过传递这些参数来再次调用函数。 在这种情况下,我们将磁盘堆栈分为两部分。 最大的磁盘( 第n个磁盘)在一部分中,所有其他磁盘( n-1 )在第二部分中。 在那里,我们为-(n-1)两次调用该方法。

tower(disk - 1, source, destination, intermediate)

As we said we pass total_disks_on_stack — 1 as an argument. And then again we move our disk like this:

正如我们所说,我们传递了total_disks_on_stack — 1作为参数。 然后再次像这样移动磁盘:

move disk from source to destination

After that we again call our method like this:

之后,我们再次调用我们的方法,如下所示:

tower(disk - 1, intermediate, source, destination)

Let’s see our full pseudocode:

让我们看一下完整的伪代码:

tower(disk, source, inter, dest)IF disk is equal 1, THENmove disk from source to destinationELSEtower(disk - 1, source, destination, intermediate)   // Step 1move disk from source to destination                 // Step 2tower(disk - 1, intermediate, source, destination)   // Step 3END IFEND

This is the tree for three disks:

这是三个磁盘的树:

This is the full code in Ruby:

这是Ruby中的完整代码:

def tower(disk_numbers, source, auxilary, destination)if disk_numbers == 1puts "#{source} -> #{destination}"returnendtower(disk_numbers - 1, source, destination, auxilary)puts "#{source} -> #{destination}"tower(disk_numbers - 1, auxilary, source, destination)nil
end

Call tower(3, 'source','aux','dest')

呼叫tower(3, 'source','aux','dest')

Output:

输出:

source -> dest
source -> aux
dest -> aux
source -> dest
aux -> source
aux -> dest
source -> dest

It took seven steps for three disks to reach the destination. We call this a recursive method.

三个磁盘到达目标位置花费了七个步骤。 我们称其为递归方法

时间复杂度和空间复杂度计算 (Time complexity and space complexity calculations)

时间复杂度 (Time complexity)

When we run code or an application in our machine it takes time — CPU cycles. But it’s not the same for every computer. For example, the processing time for a core i7 and a dual core are not the same. To solve this problem there is a concept used in computer science called time complexity.

当我们在计算机上运行代码或应用程序时,这需要时间-CPU周期。 但这并不是每台计算机都一样。 例如,内核i7和双核的处理时间不相同。 为了解决这个问题,计算机科学中使用了一个称为时间复杂度的概念。

Time complexity is a concept in computer science that deals with the quantification of the amount of time taken by a set of code or algorithm to process or run as a function of the amount of input.

时间复杂度是计算机科学中的一个概念,用于处理一组代码或算法根据输入量进行处理或运行所花费的时间量。

Time complexity is a concept in computer science that deals with the quantification of the amount of time taken by a set of code or algorithm to process or run as a function of the amount of input.

时间复杂度是计算机科学中的一个概念,用于处理一组代码或算法根据输入量进行处理或运行所花费的时间量。

In other words, time complexity is essentially efficiency, or how long a program function takes to process a given input. — techopedia

换句话说,时间复杂度实质上是效率,即程序功能处理给定输入所花费的时间。 —技术百科

The time complexity of algorithms is most commonly expressed using big O notation. It’s an asymptotic notation to represent the time complexity.

算法的时间复杂度通常使用大O表示法表示 。 它是表示时间复杂度的一种渐近符号。

Now, the time required to move n disks is T(n). There are two recursive calls for (n-1). There is one constant time operation to move a disk from source to the destination, let this be m1. Therefore:

现在,移动n个磁盘所需的时间T(n)。 ( n-1 )有两个递归调用。 有一个恒定时间操作将磁盘从源移动到目标,将其设为m1 。 因此:

T(n) = 2T(n-1) + m1    ..... eq(1)

And

T(0) = m2, a constant   ...... eq(2)
From eq (1)
T(1) = 2T(1-1) + m1= 2T(0)+m1= 2m2 + m1 ..... eq(3) [From eq 2]
T(2) = 2T(2-1) + m1= 2T(1) + m1= 4m2 + 2m1 + m1 .... eq(4) [From eq(3)]
T(3) = 2T(3-1) + m1= 2T(2) + m1= 8m2 + 4m1 + 2m1 + m1  [From eq(4)]

From these patterns — eq(2) to the last one — we can say that the time complexity of this algorithm is O(2^n) or O(a^n) where a is a constant greater than 1. So it has exponential time complexity. For the single increase in problem size, the time required is double the previous one. This is computationally very expensive. Most of the recursive programs take exponential time, and that is why it is very hard to write them iteratively.

从等式(eq(2)到最后一个),我们可以说该算法的时间复杂度为O(2 ^ n)O(a ^ n) ,其中a的常数大于1。因此它具有指数级时间复杂度。 对于问题规模的单次增加,所需时间是前一次的两倍。 这在计算上非常昂贵。 大多数递归程序都花费指数时间,这就是为什么很难迭代编写它们的原因。

空间复杂度 (Space complexity)

After the explanation of time complexity analysis, I think you can guess now what this is…This is the calculation of space required in ram for running a code or application.

在解释了时间复杂度分析之后,我想您现在可以猜测这是什么……这是ram中运行代码或应用程序所需的空间的计算。

In our case, the space for the parameter for each call is independent of n, meaning it is constant. Let it be J. When we do the second recursive call, the first one is over. That means that we can reuse the space after finishing the first one. Hence:

在我们的示例中,每个调用的参数空间均独立于n , 表示它是恒定的。 让它成为J。 当我们进行第二次递归调用时,第一个结束。 这意味着我们可以在完成第一个空间后重新使用空间。 因此:

T(n) = T(n-1) + k .... eq(1)
T(0) = k, [constant] .... eq(2)
T(1) = T(1-1) + k= T(0) + k= 2K
T(2) = 3k
T(3) = 4k

So the space complexity is O(n).

因此,空间复杂度为O(n)

After these analyses, we can see that time complexity of this algorithm is exponential but space complexity is linear.

经过这些分析,我们可以看到该算法的时间复杂度是指数级的,但是空间复杂度是线性的。

结论 (Conclusion)

From this article, I hope you can now understand the Tower of Hanoi puzzle and how to solve it. Also, I tried to give you some basic understanding about algorithms, their importance, recursion, pseudocode, time complexity, and space complexity. If you want to learn these topics in detail, here are some well-known online courses links:

希望通过这篇文章,您现在可以了解“ 河内塔”难题及其解决方法。 另外,我尝试为您提供有关算法,算法的重要性,递归,伪代码,时间复杂度空间复杂度的一些基本知识 如果您想详细学习这些主题,请访问一些著名的在线课程链接:

  1. Algorithms, Part I

    算法,第一部分

  2. Algorithms, Part II

    算法,第二部分

  3. The Google course on Udacity

    Google关于Udacity的课程

  4. Javascript Algorithms And Data Structures Certification (300 hours)

    Javascript算法和数据结构认证(300小时)

You can visit my data structures and algorithms repo to see my other problems solutions.

您可以访问我的数据结构和算法存储库 看我其他问题的解决方案。

I am on GitHub | Twitter | LinkedIn

我在GitHub | 推特 | 领英

翻译自: https://www.freecodecamp.org/news/analyzing-the-algorithm-to-solve-the-tower-of-hanoi-problem-686685f032e3/

河内之塔算法

河内之塔算法_如何解决河内问题之塔-图解算法指南相关推荐

  1. 两个矩阵是否相交的算法_刷透近200道数据结构与算法,成功加冕“题王”,挤进梦中的字节!...

    不管是学生还是已经工作的人,我想彼此都有一个相同的梦想:进大厂! 眼看着2020年还有个三十来天就要完美收尾了,那么如何才能在未来三个月弯道超车赶上"金三银四的春招",进入梦寐以求 ...

  2. umap算法_生命科学中的 UMAP(降维算法)

    UMAP应该说是目前最好的降维算法了,能最大程度的保留原始数据的特征同时大幅度的降低特征维数. 这是<生命科学的数理统计和机器学习>的相关探讨,我试图介绍生物信息学.生物医学.遗传学等常见 ...

  3. 推荐系统算法_机器学习和推荐系统(二)推荐算法简介

    推荐算法简介 一. 基于人口统计学的推荐算法 二.基于内容的推荐算法 三. 基于协同过滤的推荐算法 协同过滤(Collaborative Filtering , CF) 基于近邻的系统过滤 基于用户( ...

  4. etc的常见算法_(转)8种常见机器学习算法比较

    机器学习算法太多了,分类.回归.聚类.推荐.图像识别领域等等,要想找到一个合适算法真的不容易,所以在实际应用中,我们一般都是采用启发式学习方式来实验.通常最开始我们都会选择大家普遍认同的算法,诸如SV ...

  5. 一致性hash算法_(图文案例)一致性哈希算法详解 一点课堂(多岸教育)

    一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...

  6. python50种算法_一文洞悉Python必备50种算法

    本文是一些机器人算法(特别是自动导航算法)的Python代码合集. 其主要特点有以下三点:选择了在实践中广泛应用的算法:依赖最少:容易阅读,容易理解每个算法的基本思想.希望阅读本文后能对你有所帮助. ...

  7. redis实现轮询算法_白话分布式系统中的一致性哈希算法

    本文首发于:白话分布式系统中的一致性哈希算法 微信公众号:后端技术指南针 持续输出干货 欢迎关注! 通过本文将了解到以下内容:分布式系统的概念和作用 分布式系统常用负责均衡策略 普通哈希取模策略优缺点 ...

  8. 文本聚类分析算法_读书笔记(8)kmeans聚类算法及应用

    1.问题导入 假如有这样一种情况,在一天你想去某个城市旅游,这个城市里你想去的有70个地方,现在你只有每一个地方的地址,这个地址列表很长,有70个位置.事先肯定要做好攻略,你要把一些比较接近的地方放在 ...

  9. 动态分区分配的“首次适应算法_无人机集群——航迹规划你不知道的各种算法优缺点...

    我们都知道无人机(UAV )因具有可探测性低.造价低廉.不惧伤亡.起降简单.操作灵活.系统配置多样化.自动控制智能化等特点,因而在未来一体化联合作战中扮演越来越重要的角色.然而早期的无人机都是按照地面 ...

最新文章

  1. opencv 保存读取mat
  2. springboot 加载mybatis的流程
  3. liunx php的项目地址,在 Linux 配置 PHP 项目
  4. Zabbix篇四:钉钉机器人报警
  5. eclipse中基于maven构建多模块项目
  6. VC6中编译器/zm问题
  7. Android包管理机制(二)PackageInstaller安装APK
  8. windows域管理
  9. python google地图_Google地图下载
  10. Vue2-Vue3.0学习笔记(2021年黑马程序员最新视频)
  11. GitHub建立个人网站(一)
  12. WinForm PictureBox加载图片方法
  13. yolov5-5.0训练模型+瑞芯微rv1126上实现模型部署
  14. 基于matlab的锁相环频率合成器,锁相环与频率合成器电路设计
  15. 美团扫码付小程序的优化实践
  16. linux企业微信清理存储空间,微信系列——关闭微信企业号应用
  17. Valens VS010TX/VS010RX-A1 HDBaseT 70米延长器
  18. (地理国情监测)arcgis使用python,做arctoolbox,渔网裁剪gdb里的要素,四等分
  19. 惠普Gbe2c以太网交换机安装配置指南
  20. 如何选择TVS二极管

热门文章

  1. 0224 2101循环笔记
  2. 获得连接对象 jdbc 20210412_204123.mp4
  3. 草稿 9206需抄写 1129
  4. 前端开发 字体样式的演练0229
  5. 字符串拼接与打印相关2
  6. mysql kill 超过1分钟的语句
  7. IDEA远程调试Tomcat
  8. Android 重写onBackPressed()方法 不执行问题
  9. project euler Problem 52
  10. Unix EM乱码问题