带逐位最大值约束的固定长度整数分区Python实现优化问询
高效实现方案
你的核心需求本质是带逐位上限约束的固定长度整数分拆,原实现的冗余问题根源是把无差异的同槽位容量拆成独立令牌生成组合,天然会产生海量同值重复项,需要靠Counter、set做无意义的兜底去重。
下面给出的递归回溯实现完全消除了上述冗余,全程不会生成重复中间结果,也不需要额外的去重、计数开销:
def partition(number: int, max_vals: tuple): slot_count = len(max_vals) # 预计算后缀位的总可承载上限,避免递归过程中重复求和 suffix_capacity = [0] * (slot_count + 1) for i in range(slot_count - 1, -1, -1): suffix_capacity[i] = suffix_capacity[i + 1] + max_vals[i] # 提前校验总容量是否足够凑出目标数 if suffix_capacity[0] < number: return def dfs(current_pos: int, remaining: int, path: list): # 处理到最后一个槽位时,剩余值可直接作为该位的取值 if current_pos == slot_count - 1: if remaining <= max_vals[current_pos]: yield tuple(path + [remaining]) return # 当前槽位的合法取值上下界剪枝 upper = min(max_vals[current_pos], remaining) # 下界:若取值过小,剩余后续槽位的总容量将无法承载剩余需要分配的数值 lower = max(0, remaining - suffix_capacity[current_pos + 1]) for val in range(lower, upper + 1): path.append(val) yield from dfs(current_pos + 1, remaining - val, path) path.pop() yield from dfs(0, number, [])
方案优势
- 无重复中间开销:沿着槽位顺序逐位确定合法取值,每一步直接构造最终的分拆结果,完全不需要
Counter实例化、set去重这类额外操作 - 主动剪枝减少无效遍历:通过上下界提前过滤掉不可能产生合法结果的分支,避免在无效路径上浪费计算资源
- 性能对比显著:以示例输入
number=5, max_vals=(1,0,3,4)为例,原实现需要生成C(8,5)=56个组合项,最终仅能得到7个合法结果,冗余率达87.5%;递归实现全程仅遍历21个合法取值分支,无任何冗余计算
注:实现输出的结果顺序与示例略有差异,但覆盖的合法分拆项完全一致,若需要和示例的输出顺序对齐,仅需将最终生成的结果做一次排序即可,不会影响整体性能。
内容的提问来源于stack exchange,提问作者Ziofil
相关产品推荐
相关产品推荐

