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

如何查找和为给定值的严格递减正整数组合并优化低效实现代码

原代码问题分析
  • 时间复杂度过高:原代码采用暴力枚举所有组合的思路,从1~N-1中选取任意K个元素的组合总数为2^(N-1),属于指数级复杂度。N=50时组合总量超过500万亿,自然需要数小时才能跑完;N=200时不可能在可接受时间内执行完成,所谓的结果错误基本都是代码未执行完毕导致的误判。
  • 无效遍历过多:K个严格递减正整数的最小和为1+2+…+K = K*(K+1)/2,当这个值大于N时不可能存在符合要求的组合,原代码将K遍历到N,做了大量无用计算。
优化方案

你需要实现的功能本质是计算将N拆分为若干互不相同正整数的分拆数,再减去1(排除仅含N本身的单个元素组合,和你给出的示例规则对齐),用动态规划可以将复杂度降到多项式级别:

动态规划实现(仅计数,效率最高)

def solution(N):
    dp = [0] * (N + 1)
    dp[0] = 1
    for i in range(1, N + 1):
        # 从后往前遍历避免重复使用同一个数值
        for j in range(N, i - 1, -1):
            dp[j] += dp[j - i]
    # 减去仅包含N本身的单元素组合
    return dp[N] - 1

res = solution(50)
print(res)

该方案时间复杂度为O(N²),空间复杂度为O(N),N=200时可以秒出结果,N=1000也仅需几毫秒。

无itertools的全组合实现

如果需要输出所有符合要求的组合而非仅计数,可以用带剪枝的递归回溯实现,完全不依赖第三方库:

def get_all_combinations(N):
    res = []
    def backtrack(remaining, max_allowed, path):
        if remaining == 0:
            # 排除长度为1的单元素组合
            if len(path) >= 2:
                res.append(path.copy())
            return
        # 下一个数必须小于前一个数,且不超过剩余需要凑的数值
        for num in range(min(max_allowed - 1, remaining), 0, -1):
            path.append(num)
            backtrack(remaining - num, num, path)
            path.pop()
    backtrack(N, N, [])
    return res, len(res)

# 测试输入8
combs, count = get_all_combinations(8)
print(count) # 输出5,和示例对齐
print(combs) # 输出[[7, 1], [6, 2], [5, 3], [5, 2, 1], [4, 3, 1]]

该方案通过剪枝避免了大量无效路径,效率远高于暴力枚举,N=50时也可以快速输出所有组合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:24:06