基于特定字典结构的递归记忆化实现技术问询
嘿,我来帮你搞定这个记忆化实现的问题!先仔细看了你给的ROWS字典结构:
ROWS = {368: [247, 257], 257: [368], 2468: [357], 357: [2468], 358: [247], 247: [358, 368]}
每个键是一个数字节点,对应的邻居列表里的节点完全不共享键的任何数字——这个规则是我们实现的核心前提。结合这类结构的常见问题(比如最长路径、路径计数),我给你整理了一套记忆化实现方案:
记忆化实现方案
核心思路
记忆化说白了就是「缓存已经算过的结果」,避免递归时反复遍历相同的路径分支。我们会用一个memo字典来存缓存:键是能唯一标识当前计算状态的标记,值是对应的计算结果(比如路径长度、路径数量)。
常见场景的具体实现
场景1:计算从某个节点出发的最长路径长度
这里要注意:节点之间可能形成双向环(比如368↔257),所以递归时得跳过父节点,避免无限循环。
ROWS = {368: [247, 257], 257: [368], 2468: [357], 357: [2468], 358: [247], 247: [358, 368]} # 缓存字典:键是(当前节点, 父节点),值是该状态下的最长路径长度 memo = {} def longest_path(start_node, parent_node=None): cache_key = (start_node, parent_node) # 先查缓存,有结果直接返回,不用重复计算 if cache_key in memo: return memo[cache_key] # 初始值:至少包含当前节点自己,长度为1 max_length = 1 for neighbor in ROWS[start_node]: # 跳过父节点,防止循环 if neighbor == parent_node: continue # 递归计算邻居的最长路径,加上当前节点的长度 current_length = 1 + longest_path(neighbor, start_node) if current_length > max_length: max_length = current_length # 把计算结果存入缓存 memo[cache_key] = max_length return max_length # 测试:计算从368出发的最长路径 print(longest_path(368)) # 输出3,对应路径368→247→358
场景2:统计从某个节点出发的所有合法路径数量
同样用父节点避免循环,缓存每个状态下的路径总数:
ROWS = {368: [247, 257], 257: [368], 2468: [357], 357: [2468], 358: [247], 247: [358, 368]} memo = {} def count_total_paths(start_node, parent_node=None): cache_key = (start_node, parent_node) if cache_key in memo: return memo[cache_key] # 初始值:当前节点自己算一条路径 total = 1 for neighbor in ROWS[start_node]: if neighbor == parent_node: continue # 累加从邻居出发的所有路径(当前节点可以和这些路径拼接) total += count_total_paths(neighbor, start_node) memo[cache_key] = total return total # 测试:统计368的所有合法路径 print(count_total_paths(368)) # 输出4,对应路径:368、368→247、368→247→358、368→257
优化小提示
- 缓存键的设计:一定要能唯一标识当前计算状态,这里因为不能回跳父节点,所以用
(当前节点, 父节点)当键;如果你的问题有其他限制(比如路径长度上限),要把这些限制也加入缓存键。 - 缓存复用:如果需要计算多个节点的结果,
memo字典可以复用,不用每次重新初始化。 - 避免冗余计算:递归前先查缓存是记忆化的核心,一定要放在最前面。
如果你的具体问题不是这两个(比如求所有节点的最长路径、或者特定数字规则的路径),可以补充细节,我再帮你调整方案!
内容的提问来源于stack exchange,提问作者btrif
相关产品推荐
相关产品推荐

