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

请解释这段求解目标值组合的递归代码工作原理

拆解这段递归组合求和代码的逻辑

首先先提个小问题:你贴的代码里函数参数是distances,但函数内部用了d,这是笔误,得改成一致的(比如都用distances),不然运行会报NameError。接下来咱们一步步拆解它的递归逻辑:

核心功能

这段代码的目的是找出distances列表中所有**元素相加等于目标值r**的组合——注意因为会遍历整个列表的元素,所以列表里的重复元素(比如示例里的两个5)会生成对应的有效组合。

递归的终止条件

递归函数的关键就是先明确终止情况:

  • 当r < 0:说明当前选择的元素加起来已经超过目标值了,这条路走不通,直接返回空列表[],表示没有可行解。
  • 当r == 0:说明刚好凑到了目标值,这时候返回[[]]——一个包含空列表的列表。这个空列表很重要,它是后续追加元素的“容器”,相当于告诉上层递归:“我找到了一个凑到0的方法,你把刚才选的元素加进来就行”。

递归的核心循环逻辑

接下来是最关键的循环部分,咱们逐行拆解:

  1. 初始化空列表solutions,用来存储所有有效的组合。
  2. 遍历distances里的每一个元素last_distance:
    • 递归调用greedy(r - last_distance, distances):意思是假设我现在选了这个last_distance元素,那剩下需要凑的目标值就是r - last_distance,我去递归找能凑出这个剩余值的所有组合。
    • 遍历递归返回的每一个组合combo:把当前的last_distance追加到combo末尾。比如递归返回[[5]](表示能凑出5的组合是[5]),追加当前的5就变成[[5,5]],这就是一个和为10的有效组合。
    • 检查这个组合是不是已经在solutions里了,如果没有就加进去,避免重复的组合被存入。

用你的示例走一遍流程

拿你给的例子:distances = [3,5,2,5],目标r=10

  • 第一次循环选last_distance=3,递归找r=7的组合:
    • 在r=7的递归里,选last_distance=5,递归找r=2的组合:
      • 在r=2的递归里,选last_distance=2,递归找r=0,返回[[]],把2追加进去得到[[2]]。
      • 回到r=7的层,把5追加到[2]里,得到[[2,5]]。
      • 回到最外层,把3追加到[2,5]里,得到[[2,5,3]](也就是你说的[3,2,5],只是顺序反过来了,组合是有效的),加入solutions。
  • 然后循环选last_distance=5,递归找r=5的组合:
    • 在r=5的递归里,选last_distance=5,递归找r=0返回[[]],追加5得到[[5]]。
    • 回到最外层,把5追加到[5]里,得到[[5,5]],加入solutions。
  • 后面遍历2和第二个5的时候,可能会生成类似[5,3,2]或者重复的[5,5],但因为solutions.__contains__(combo)的检查,重复的组合不会被再次加入。

代码可以优化的点

  • 参数名不一致:刚才说的,函数参数distances和内部的d要统一,不然会报错。
  • 去重效率低:solutions.__contains__(combo)是遍历整个列表检查,数据量大的时候很慢。而且如果把[3,2,5]和[2,3,5]当成同一个组合的话,应该先对组合排序再检查,不然这两个会被当成不同的组合存入。
  • 重复计算:递归过程中会多次计算同一个r的情况,比如多次计算r=5,可以用记忆化(比如用字典存已经计算过的r对应的结果)来大幅提升效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:28:34