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

符合区间要求的数组选数组合计数实现复杂度及优化咨询

问题解答

1 两种实现的最坏时间复杂度

我们先定义M为原数组筛选后符合[MIN, MAX]区间要求的元素个数,最坏情况下M=N(所有元素都符合区间要求)。

  • 第一种暴力生成组合的实现:
    最坏场景为K=1,需要生成所有长度从1到M的非空组合,总组合数为2^M - 1,每个组合生成时需要遍历对应长度的元素存入元组,总时间复杂度为O(M * 2^M),最坏可到O(N * 2^N),数组长度稍大就会严重超时。
  • 第二种组合数求和的实现:
    最坏场景为K=1,需要循环计算M次组合数,每次计算组合数NcR(n,r)的时间复杂度为O(min(r, n-r)),最坏单轮计算为O(M),总时间复杂度为O(M²),最坏可到O(N²),性能远优于暴力实现。

2 基于二项式特性的优化方案

完全可以利用你提到的二项式特性做优化,核心优化思路有两个:

2.1 用总组合数做差值减少计算量

根据二项式展开总和sum_{r=0}^M C(M,r) = 2^M,我们可以把要求的和转换为:
sum_{r=K}^M C(M,r) = 2^M - sum_{r=0}^{K-1} C(M,r)
判断M-K+1和K的大小,选择计算次数更少的方式:如果K > M/2,就直接从K累加到M;如果K <= M/2,就计算0到K-1的和再用2^M减去,最多只需要计算floor(M/2)+1次组合数,计算量直接减半。

2.2 边界情况提前处理

  • 如果M < K,直接返回0,无需后续计算
  • 如果K=0,直接返回1 << M即可

优化后的代码示例

from math import gcd

def count_valid_combinations(arr, MIN, MAX, K):
    # 第一步筛选符合区间的元素
    temp_list = [x for x in arr if MIN <= x <= MAX]
    M = len(temp_list)
    # 提前处理边界
    if M < K:
        return 0
    if K == 0:
        return 1 << M
    
    def NcR(n, r):
        if r <0 or r >n:
            return 0
        if (n - r < r):
            r = n - r
        p = 1
        k = 1
        while r:
            p *= n
            k *= r
            m = gcd(p, k)
            p //= m
            k //= m
            n -=1
            r -=1
        return p
    
    total = 1 << M
    # 选择计算量更小的累加方式
    if K <= M // 2:
        # 算前K项的和再减
        sum_prev = 0
        for i in range(K):
            sum_prev += NcR(M, i)
        return total - sum_prev
    else:
        # 直接算从K到M的和
        sum_target = 0
        for i in range(K, M+1):
            sum_target += NcR(M, i)
        return sum_target

内容的提问来源于stack exchange,提问作者Mrinmay Dhar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 06:39:00