如何用 Python 在一个数组中找出任意几个数的和等于给定数?
本来一开始想尝试写个报账的小脚本,后来发现水比较深啊!希望有大佬可以指点迷津。
如何用 Python 在一个数组中找出任意几个数的和等于给定数?
3sum?
def find_sum_combinations(nums, target):
"""
找出数组中所有和为target的数字组合
返回组合列表,每个组合以列表形式存储
"""
def backtrack(start, current_sum, path):
if current_sum == target:
result.append(path[:])
return
if current_sum > target or start >= len(nums):
return
for i in range(start, len(nums)):
# 避免重复组合(如果数组有重复元素)
if i > start and nums[i] == nums[i-1]:
continue
path.append(nums[i])
backtrack(i + 1, current_sum + nums[i], path)
path.pop()
nums.sort() # 排序便于剪枝和去重
result = []
backtrack(0, 0, [])
return result
# 使用示例
if __name__ == "__main__":
arr = [2, 3, 6, 7, 1, 4]
target = 7
combinations = find_sum_combinations(arr, target)
print(f"数组: {arr}")
print(f"目标和: {target}")
print("找到的组合:")
for combo in combinations:
print(f" {compo} = {sum(compo)}")
这个回溯算法会找出所有不重复的组合。算法核心是:
- 先排序数组,便于剪枝(当当前和超过target时停止搜索)
- 使用深度优先搜索遍历所有可能的组合
- 通过
i > start and nums[i] == nums[i-1]跳过重复元素避免重复组合
时间复杂度是O(2^n),对于小规模数据完全够用。如果数组很大或target很大,可以考虑动态规划解法。
一句话建议:回溯法最适合这类组合搜索问题。
https://en.wikipedia.org/wiki/Subset_sum_problem
NP-complete 的,只能暴搜了
所以用 的写法可能是比较优美的解决方案了
naive 的动态规划对付这个问题应该已经够了吧…
所谓动态规划做法相比于暴搜真正的优化不外乎是把状态从有序的数列给合并成无序的子集,那既然如此为何不直接对着所有子集枚举呢,就像 2L 所做的那样,还省下了用来记忆状态的空间.
2^nN 和 sumN 一样吗…
这不是动态规划的教材问题吗?
我觉得关于动态规划的讨论已经偏离了楼主的需求= =
我去年弄过这个东西,用遗传算法,有想不到的结果。
sum*N 又是哪里来的……
dp 的状态数是 sum * N 啊…所以复杂度也是这个
对于日常情况来说 给定数 常常远小于 2^条目数
#9 为什么?
我感觉动态规划已经不符合楼主的『小脚本』的需求了,即使暴力穷举也能在短时间内满足其需求
是你觉得动态规划太复杂,但其实并非如此
我没有讲过动态规划复杂,相反我也在实际的代码中使用
但我仍然没有觉得楼主的需求有任何必要使用动态规划
这个 leetcode 有吧 小脚本建议穷举
是要求方案数,还是输出所有方案,还是求是否存在。说清楚。不然没人能给你正确答案。

