总结问题框架:1.明确的问题 2.问题的原因 3.解决的多种方案 4.推荐的方案
总结: 汉诺塔问题/递归思想
1.问题: 明确问题
1.1 在汉诺塔规则之下,通过Python代码模拟 '圆盘' 的移动路径,并打印.
2.原因: 准确清晰的规则、汉诺塔步骤的本质理解、递归的数学定义、计算机上递归函数的本质逻辑与设计步骤。
2.1 明确汉诺塔的规则
人的角度:三根柱子,在一根柱子上有n个圆盘,大小是自上而下,从小到达排列.规则:小圆盘不能在大圆盘之下,移动n个圆盘到第三柱子.
2.2 明确规则下的本质规律 (a,b,c=柱子顺序)
n=1时, a>>>c柱子
n=2时,
a移动到b柱
a移动到c
b移动到c
n = 3, 1号和2号看成整体, 3号单独
第 一 步:1/2号 a移动b, 这个结果变成n=2的情形,重复n=2的步骤.
第 二 步:3号 a移动到c , 基准情形,不会变的.
第 三 步:1/2号 b移动到c, 本质同第一步,将柱子上圆盘移动到目标柱,不过开始变成了b柱, 此时把b看成a (a与b无顺序) ,步骤顺序同第一步.
得出: 根据以上步骤 圆盘数量 = n 时,
第 一 步:(n-1)个 a移动b, 这个结果变成n-2的情形,重复n-3的情形...直到剩2个圆盘执行n=2,a移到b
第 二 步:n号 a移动到c , 基准情形,不会变的.
第 三 步:(n-1)个 b移动到c, 这个结果变成n-2移动到另一个柱子, 把b当做a ,重复的仍是第一步.
移动路径的本质:
圆盘数n为1时,直接移动到c柱上
圆盘数n>1时,①直接(n-1)移动a到b, ②n号 a移动到c, ③(n-1)个 b移动到c. 且①与③本质顺序相同.
2.3 规律转化代码:
2.3.1 递归的数学定义:一个复杂问题能被拆解为结构完全相同的子问题,并最终收敛于一个确定的基准情形时,通过“自身定义自身”来构建逻辑的过程。
1.属性:
自相似(子问题和原问题长得一样)
可分解(规模能不断变小)
有原点(必须有一个确定的停止点/基准)
2.3.2 计算机的角度考虑问题:
1.人考虑问题:
会把文字转化图像,再进行理解 (柱子顺序,圆盘大小概念,小必须在大之上)
在抽象化层面 易存在限制性,a柱,b柱,c柱独立存在
2.计算机的属性:
无抽象概念限制 (柱子顺序,圆盘大小概念,小必须在大之上) 三个柱子之间可交换顺序,达到控制变量的目的
按逻辑执行
重复度高
结果偏差低
2.3.3 计算机递归函数的属性
①代码语言类型:例如Python的解释型语言,自上而下执行,
②递归函数的逻辑:
1.无限调用自身: 若无基准情形,导致“栈溢出”崩溃
2.基准情形:递归出口 或 终止条件
3.递归步骤:
这是将问题分解的步骤。
它必须将原问题转化为一个或多个规模更小的子问题,并调用自身来解决这些子问题。
关键点: 每一次递归调用,问题的规模都必须比上一次更小,从而无限接近基准情形。
③递归函数的设计步骤:
第 1 步:明确函数的功能
第 2 步:寻找基准情形
第 3 步:寻找“递归关系” ,大问题拆解为:当前的一步操作 + 子问题的结果。
第 4 步:验证收敛性:确保每一次递归 ‘调用’ 都向着 ‘基准情形’ 逼近。例参数 n 在不断减小,最终一定能等于基准情形中的值。
④其它属性:
变量的输入输出:def 函数时,设置形式参数
变量传递:核心逻辑-函数传递参数'按位置'接受参数,递归函数每次调用自身,可改变参数位置,从而巧妙改变参数.这是利用函数传参的属性,节省计算机资源
条件的判定:基准情形需要放在首位执行,否则易栈溢出崩溃.再组合其它基准情形的代码块.
未想到的方面: 待补充
3.多种解决方案
3.1 定义递归函数
本质: 问题是递归类型,得出移动路径,计算机的递归函数可模拟移动路径并输出结果。
3.2 模拟代码
本质:
计算机模拟人的操作步骤.
定义圆盘与柱子对应的数字.
根据柱子的奇偶性.圆盘的奇偶性.
规则限制:通过数字大小,小数字必须在上.
设计判断条件.
得出移动路径.
4.推荐方案
4.1 递归方式 优势与局限性分析
优势:得出本质,最简洁的代码,实现复杂功能
局限性:递归出口,与递归数量需限制.否则容易栈溢出崩溃
4.2 机器模拟人方式 优势与局限性分析
优势: 以人的思维方式,去模拟,容易理解代码
局限性:
1.代码设计过程多,容错率低.
2.多一行代码,多一个计算机资源
结论:各有优势与局限,需根据实际使用场景进而判断.