You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效递归遍历多路径数组,求解二维数组最长序列路径?

如何递归遍历多路径数组以找到最长路径链?

嘿,我完全懂你现在卡住的点——要遍历所有可能的路径找到最长链,很容易陷入要么重复计算要么漏走分支的困境,尤其是当节点之间还有环的时候。咱们一步步拆解这个问题,找到最高效的解决办法。

问题分析

你已经有了每个节点的可访问路径列表,但目前只能计算单条路径,核心问题在于如何遍历所有分支路径并避免重复计算或循环。首先要明确:如果路径中存在环(比如你的例子里(0,0)和(0,1)互相指向),那如果允许重复访问节点,最长路径会无限长,所以默认我们要找的是不重复访问节点的最长简单路径。

方案1:无环场景下的高效递归(记忆化优化)

如果你的路径是无环的(比如DAG结构),那记忆化递归是最高效的方式——每个节点的最长路径只需要计算一次,后续直接复用结果。

实现步骤

  1. 先把节点数据转换成按坐标快速查找的结构(比如字典),方便快速定位节点。
  2. 用一个缓存字典memo存储每个坐标对应的最长路径长度,避免重复计算。
  3. 递归函数逻辑:
    • 如果当前坐标在缓存里,直接返回缓存值。
    • 如果当前节点没有后续路径,最长路径就是1(只有自己)。
    • 否则遍历所有后续节点,递归获取每个节点的最长路径,取最大值加1作为当前节点的最长路径,存入缓存后返回。

代码示例(Python)

nodes = [
    {"value": 8, "row": 0, "col": 0, "paths": [{"row": 1, "col": 0}, {"row": 0, "col": 1}]},
    {"value": 2, "row": 0, "col": 1, "paths": [{"row": 1, "col": 1}, {"row": 0, "col": 0}]},
    {"value": 4, "row": 0, "col": 2, "paths": []},
    {"value": 0, "row": 1, "col": 0, "paths": [{"row": 0, "col": 0}, {"row": 2, "col": 1}, {"row": 1, "col": 1}]},
    {"value": 6, "row": 1, "col": 1, "paths": [{"row": 0, "col": 1}, {"row": 1, "col": 2}]},
    {"value": 1, "row": 1, "col": 2, "paths": [{"row": 2, "col": 2}, {"row": 2, "col": 1}, {"row": 1, "col": 1}]},
    {"value": 3, "row": 2, "col": 0, "paths": [{"row": 2, "col": 1}]},
    {"value": 7, "row": 2, "col": 1, "paths": [{"row": 1, "col": 2}, {"row": 2, "col": 0}]},
    {"value": 9, "row": 2, "col": 2, "paths": [{"row": 1, "col": 2}]}
]

# 构建坐标到节点的映射,方便快速查找
node_lookup = {(node["row"], node["col"]): node for node in nodes}
memo = {}

def longest_path_from(row, col):
    # 优先从缓存取结果,避免重复计算
    if (row, col) in memo:
        return memo[(row, col)]
    
    current_node = node_lookup[(row, col)]
    # 没有后续路径,最长路径就是自己
    if not current_node["paths"]:
        memo[(row, col)] = 1
        return 1
    
    # 遍历所有后续节点,找到最长的子路径
    max_sub_length = 0
    for path in current_node["paths"]:
        sub_length = longest_path_from(path["row"], path["col"])
        if sub_length > max_sub_length:
            max_sub_length = sub_length
    
    # 当前节点的最长路径 = 1(自己) + 最长子路径
    result = 1 + max_sub_length
    memo[(row, col)] = result
    return result

# 遍历所有节点,找到全局最长路径
max_total = 0
for node in nodes:
    current_len = longest_path_from(node["row"], node["col"])
    if current_len > max_total:
        max_total = current_len

print(f"最长路径长度(无环假设): {max_total}")

方案2:带环场景下的递归(跟踪访问节点)

但你的例子里存在环,这时候上面的代码会陷入无限递归。所以需要在递归时跟踪当前路径已经访问过的节点,避免重复进入同一个节点。

实现步骤

  1. 递归函数新增一个visited集合参数,记录当前路径中已经访问过的节点。
  2. 如果当前节点已经在visited里,说明遇到环,返回0(不能继续延伸路径)。
  3. 每次递归时复制visited集合,加入当前节点,传递给下一层递归,避免影响其他分支路径。

代码示例(Python)

def longest_simple_path_from(row, col, visited):
    # 遇到已访问节点,停止延伸
    if (row, col) in visited:
        return 0
    
    # 复制集合,避免修改原分支的访问记录
    new_visited = visited.copy()
    new_visited.add((row, col))
    
    current_node = node_lookup[(row, col)]
    max_len = 1  # 至少包含当前节点
    
    # 遍历所有后续路径,计算最长子路径
    for path in current_node["paths"]:
        sub_len = longest_simple_path_from(path["row"], path["col"], new_visited)
        if sub_len + 1 > max_len:
            max_len = sub_len + 1
    
    return max_len

# 遍历所有节点作为起点,找到全局最长简单路径
max_simple_total = 0
for node in nodes:
    current_len = longest_simple_path_from(node["row"], node["col"], set())
    if current_len > max_simple_total:
        max_simple_total = current_len

print(f"最长简单路径长度(处理环): {max_simple_total}")

效率对比

  • 无环场景的记忆化递归:时间复杂度O(N),N是节点数量,每个节点只计算一次,效率极高。
  • 带环场景的递归:时间复杂度O(N*2^N)(最坏情况每个节点都有大量分支),但对于小规模数组(比如你给出的3x3)完全够用。如果是大规模数组,可以考虑用动态规划结合状态压缩,或者先检测环并处理。

内容的提问来源于stack exchange,提问作者hera87

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:15:29