【393】递归算法(排列组合计算,迷宫)
参考:Python 实现递归算法 - 另一个自己 - CSDN博客
用递归实现以下算法:
- Factorial
- Hannoi Tower
- Fibonacci
- 迷宫
使用递归计算组合(permutation)
- 对于一个元素的集合,直接返回值即可
- 对于多个元素的集合
- 遍历所有元素
- 对于任意一个元素与其他元素合并
代码如下:
利用 set 可以进行简单的 + - 操作
返回结果为 迭代器,也是可以遍历的
1 2 3 4 5 6 7 8 9 10 11 12 | def naive_recursive_permute(S): if len (S) < = 1 : yield list (S) else : for x in S: for P in naive_recursive_permute(S - {x}): yield [x] + P list (naive_recursive_permute({ 0 })) list (naive_recursive_permute({ 0 , 1 })) list (naive_recursive_permute({ 0 , 1 , 2 })) list (naive_recursive_permute({ 0 , 1 , 2 , 3 })) |
output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | [[ 0 ]] Out[ 2 ]: [[ 0 , 1 ], [ 1 , 0 ]] Out[ 2 ]: [[ 0 , 1 , 2 ], [ 0 , 2 , 1 ], [ 1 , 0 , 2 ], [ 1 , 2 , 0 ], [ 2 , 0 , 1 ], [ 2 , 1 , 0 ]] Out[ 2 ]: [[ 0 , 1 , 2 , 3 ], [ 0 , 1 , 3 , 2 ], [ 0 , 2 , 1 , 3 ], [ 0 , 2 , 3 , 1 ], [ 0 , 3 , 1 , 2 ], [ 0 , 3 , 2 , 1 ], [ 1 , 0 , 2 , 3 ], [ 1 , 0 , 3 , 2 ], [ 1 , 2 , 0 , 3 ], [ 1 , 2 , 3 , 0 ], [ 1 , 3 , 0 , 2 ], [ 1 , 3 , 2 , 0 ], [ 2 , 0 , 1 , 3 ], [ 2 , 0 , 3 , 1 ], [ 2 , 1 , 0 , 3 ], [ 2 , 1 , 3 , 0 ], [ 2 , 3 , 0 , 1 ], [ 2 , 3 , 1 , 0 ], [ 3 , 0 , 1 , 2 ], [ 3 , 0 , 2 , 1 ], [ 3 , 1 , 0 , 2 ], [ 3 , 1 , 2 , 0 ], [ 3 , 2 , 0 , 1 ], [ 3 , 2 , 1 , 0 ]] |
可以填写选择几个数字的排列
函数名字是组合
1 2 3 4 5 6 7 8 9 10 11 12 13 | def combination(m_list, nb): if nb = = 1 : for m in m_list: yield [m] else : for k in range ( len (m_list)): for i in combination(m_list[ 0 :k] + m_list[k + 1 :], nb - 1 ): yield [m_list[k]] + i list (combination([ 1 , 2 , 3 , 4 ], 1 )) list (combination([ 1 , 2 , 3 , 4 ], 2 )) list (combination([ 1 , 2 , 3 , 4 ], 3 )) list (combination([ 1 , 2 , 3 , 4 ], 4 )) |
output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | [[ 1 ], [ 2 ], [ 3 ], [ 4 ]] Out[ 52 ]: [[ 1 , 2 ], [ 1 , 3 ], [ 1 , 4 ], [ 2 , 1 ], [ 2 , 3 ], [ 2 , 4 ], [ 3 , 1 ], [ 3 , 2 ], [ 3 , 4 ], [ 4 , 1 ], [ 4 , 2 ], [ 4 , 3 ]] Out[ 52 ]: [[ 1 , 2 , 3 ], [ 1 , 2 , 4 ], [ 1 , 3 , 2 ], [ 1 , 3 , 4 ], [ 1 , 4 , 2 ], [ 1 , 4 , 3 ], [ 2 , 1 , 3 ], [ 2 , 1 , 4 ], [ 2 , 3 , 1 ], [ 2 , 3 , 4 ], [ 2 , 4 , 1 ], [ 2 , 4 , 3 ], [ 3 , 1 , 2 ], [ 3 , 1 , 4 ], [ 3 , 2 , 1 ], [ 3 , 2 , 4 ], [ 3 , 4 , 1 ], [ 3 , 4 , 2 ], [ 4 , 1 , 2 ], [ 4 , 1 , 3 ], [ 4 , 2 , 1 ], [ 4 , 2 , 3 ], [ 4 , 3 , 1 ], [ 4 , 3 , 2 ]] Out[ 52 ]: [[ 1 , 2 , 3 , 4 ], [ 1 , 2 , 4 , 3 ], [ 1 , 3 , 2 , 4 ], [ 1 , 3 , 4 , 2 ], [ 1 , 4 , 2 , 3 ], [ 1 , 4 , 3 , 2 ], [ 2 , 1 , 3 , 4 ], [ 2 , 1 , 4 , 3 ], [ 2 , 3 , 1 , 4 ], [ 2 , 3 , 4 , 1 ], [ 2 , 4 , 1 , 3 ], [ 2 , 4 , 3 , 1 ], [ 3 , 1 , 2 , 4 ], [ 3 , 1 , 4 , 2 ], [ 3 , 2 , 1 , 4 ], [ 3 , 2 , 4 , 1 ], [ 3 , 4 , 1 , 2 ], [ 3 , 4 , 2 , 1 ], [ 4 , 1 , 2 , 3 ], [ 4 , 1 , 3 , 2 ], [ 4 , 2 , 1 , 3 ], [ 4 , 2 , 3 , 1 ], [ 4 , 3 , 1 , 2 ], [ 4 , 3 , 2 , 1 ]] |
组合实现(对于 [a, a, b, c] 这种情况,可以事先处理为 [a1, a2, b, c] 进行操作,操作后在将 a1/a2 转化为 a)
1 2 3 4 5 6 7 8 9 10 11 12 13 | def combination(m_list, nb): if nb = = 1 : for m in m_list: yield tuple ([m]) else : for k in range ( len (m_list)): for i in combination(m_list[ 0 :k] + m_list[k + 1 :], nb - 1 ): yield tuple ( sorted ([m_list[k]] + list (i))) set ( list (combination([ 1 , 2 , 3 , 4 ], 1 ))) set ( list (combination([ 1 , 2 , 3 , 4 ], 2 ))) set ( list (combination([ 1 , 2 , 3 , 4 ], 3 ))) set ( list (combination([ 1 , 2 , 3 , 4 ], 4 ))) |
output:
1 2 3 4 5 6 7 | {( 1 ,), ( 2 ,), ( 3 ,), ( 4 ,)} Out[ 67 ]: {( 1 , 2 ), ( 1 , 3 ), ( 1 , 4 ), ( 2 , 3 ), ( 2 , 4 ), ( 3 , 4 )} Out[ 67 ]: {( 1 , 2 , 3 ), ( 1 , 2 , 4 ), ( 1 , 3 , 4 ), ( 2 , 3 , 4 )} Out[ 67 ]: {( 1 , 2 , 3 , 4 )} |
迷宫(所有路径)
从某一点为起点,到达终点,利用 DFS 方法
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # 首先需要定义四个方向的步长 # four directions # up, right, down, left item = [( - 1 , 0 ), ( 0 , 1 ), ( 1 , 0 ), ( 0 , - 1 )] def find_a_way(point_start, point_end): # 将点进栈并赋值为 False ,防止后面回来 stack.push(point_start) grid[point_start] = False # 接下来根据两种情况进行判断 if point_start = = point_end: # 这就是终点了,需要输出路径,并统计数目 stack.output() count + = 1 else : # 按照四个方向遍历 for i in range ( len (item)): point_tmp = (point_start[ 0 ] + item[i][ 0 ], point_start[ 1 ] + item[i][ 1 ]) # 如果这个点是 True,就继续往下走 if grid[point_tmp] = = True : find_a_way(point_tmp, point_end) # 将进栈的数据再吐出来,并重新复制为 True stack.pop() grid[point_start] = True |
首先判断上,如果可以,就卡开 find_a_way(point_tmp, point_end) 的位置,继续运行代码,然后看下一个点
如果碰巧上不可以,再看看右,如果右可以,继续卡在下一个 find_a_way(point_tmp, point_end) 的位置,此时每个点都会进栈并且标记为 False
...
以此类推,最终到达终点了,这时候进栈的数据可以打印出来了,然后运行 stack.pop() 和 grid[point_start] = True,把终点吐出来,并标记为 True
然后是返回来到 上一个 find_a_way(point_tmp, point_end) 的位置,然后继续运行下一个可行的方向,所有方向运行完以后,继续运行 stack.pop() 和 grid[point_start] = True,把这个点吐出来,并标记为 True
返回到上一点的下一个方向的时候,他又把上面的过程走了一遍。。。真的好复杂,有点乱了。。。
...
以此类推,最终退回到第一个点的 find_a_way(point_tmp, point_end) 的位置,继续运行 stack.pop() 和 grid[point_start] = True,把这个点吐出来,并标记为 True
一个路径执行完毕
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2015-04-16 【164】ALL_VIDEOS
2012-04-16 【032】Mark Zuckerberg