如何高效查找整数列表中和为指定值的无重复唯一组合
无重复组合求和优化方案
原代码核心性能瓶颈
原实现的性能损耗主要来自三个可优化的点:
- 冗余的后处理查重逻辑:每次匹配到符合条件的组合后,都要做排序、全局列表存在性判断,这部分操作的时间成本会随组合数量增长快速上升,是最大的性能瓶颈
- 未跳过重复元素分支:输入列表存在重复值时(比如示例中的两个5),会重复遍历取值相同的分支,生成大量重复组合,做了很多无用计算
- 剪枝不彻底:列表已经提前排序的前提下,当前元素大于剩余目标和时,后续所有元素都更大,直接终止循环即可,不需要继续遍历后续元素
优化实现思路
我们可以从根源上避免冗余操作,不需要后续查重和排序:
- 提前对输入列表做升序排序,递归时只允许选取当前位置之后的元素,保证生成的组合天然是递增的,从根源避免出现顺序不同的同值组合
- 递归遍历同一层级的元素时,跳过和前一个取值相同的元素,完全避免生成重复组合,不需要后续做全局查重
- 利用排序特性做强剪枝,当前元素大于剩余目标和时直接终止当前循环,大幅减少遍历次数
- 移除全局变量,用内部递归函数传递结果,减少副作用
优化后代码
def combo_find(nums, target): # 预处理排序,为去重和剪枝做准备 nums.sort() result = [] def backtrack(start_idx, current_path, remaining_sum): # 剩余和为0,匹配到符合条件的组合 if remaining_sum == 0: result.append(current_path.copy()) return for i in range(start_idx, len(nums)): # 剪枝:当前元素已经大于剩余和,后续元素更大,直接终止循环 if nums[i] > remaining_sum: break # 同层去重:跳过和前一个元素取值相同的分支,避免生成重复组合 if i > start_idx and nums[i] == nums[i-1]: continue # 递归回溯逻辑 current_path.append(nums[i]) # 下一层递归从i+1开始,保证不会重复选取前面的元素 backtrack(i+1, current_path, remaining_sum - nums[i]) current_path.pop() backtrack(0, [], target) return result # 示例测试 the_list = [7,6,5,5,4,3,2,1] stop_sum = 11 print(combo_find(the_list, stop_sum))
补充说明
如果你的输入列表包含负整数,需要移除if nums[i] > remaining_sum: break这行剪枝逻辑,其余逻辑保持不变即可。该优化方案相比原实现,在包含大量重复元素的长列表场景下,性能可提升数十到上百倍,可轻松处理300以上长度的输入列表。
内容的提问来源于stack exchange,提问作者user15107839
相关产品推荐
相关产品推荐

