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

如何高效筛选满足双列表总和阈值条件的list_a子集?

高效筛选满足双总和阈值条件的子集并降序排列

问题概述

需要从list_a中筛选所有满足以下条件的子集:

  • 子集对应list_b中元素的总和 ≤ 指定阈值
  • 子集对应list_c中元素的总和 ≤ 指定阈值
    最终筛选结果需按降序排列,同时要尽可能降低计算耗时。

示例:

list_a = [1, 2, 3, 4, 5]
list_b = [3,4,7,8,2]
list_c = [4,6,1,5,8]
Threshold = 12

比如子集(1,2)对应的list_b总和为3+4=7,list_c总和为4+6=10,均≤12,符合条件。

当前已实现生成所有子集的powerset函数,但直接生成所有子集再筛选的方式效率极低,需要优化筛选逻辑。

现有代码:

from itertools import chain, combinations

def powerset(s):
    if s:
        tail1 = s[1:]
        for e in chain.from_iterable(combinations(tail1, r) for r in range(len(tail1) + 1, -1, -1)):
            yield (s[0],) + e

优化方案

直接生成所有子集的时间复杂度是O(2^n),当列表长度较大时完全不可行。我们可以采用回溯剪枝的方式,在生成子集的过程中实时判断总和是否超标,一旦超标就停止继续扩展该分支,大幅减少无效计算。

步骤说明

  • 绑定元素与对应权重:将list_a、list_b、list_c的对应元素绑定为元组,方便统一处理,避免多次索引查找。
  • 回溯剪枝:递归生成子集,每添加一个元素就计算当前list_b和list_c的总和,若任一总和超过阈值则停止递归该分支。
  • 结果排序:收集所有符合条件的子集后,按「子集长度降序,同长度子集元素降序」的规则排序,满足需求中的降序要求。

实现代码

def filter_valid_subsets(list_a, list_b, list_c, threshold):
    # 绑定元素与对应的b、c权重
    elements = list(zip(list_a, list_b, list_c))
    valid_subsets = []
    
    def backtrack(start, current_subset, sum_b, sum_c):
        # 将当前子集的元素提取出来,加入结果
        valid_subsets.append(tuple(x[0] for x in current_subset))
        
        # 遍历后续元素,尝试添加
        for i in range(start, len(elements)):
            new_sum_b = sum_b + elements[i][1]
            new_sum_c = sum_c + elements[i][2]
            # 剪枝:如果任一总和超过阈值,跳过该元素
            if new_sum_b > threshold or new_sum_c > threshold:
                continue
            # 递归添加当前元素
            backtrack(i + 1, current_subset + [elements[i]], new_sum_b, new_sum_c)
    
    # 从第一个元素开始回溯
    backtrack(0, [], 0, 0)
    
    # 排序:先按子集长度降序,再按子集元素降序排列
    valid_subsets.sort(key=lambda x: (-len(x), sorted(x, reverse=True)), reverse=False)
    return valid_subsets

# 测试示例
list_a = [1, 2, 3, 4, 5]
list_b = [3,4,7,8,2]
list_c = [4,6,1,5,8]
threshold = 12

result = filter_valid_subsets(list_a, list_b, list_c, threshold)
for subset in result:
    print(subset)

代码说明

  • 回溯剪枝:每次添加元素前先计算新的总和,若超过阈值则直接跳过,避免生成大量无效子集。
  • 排序逻辑:通过lambda表达式指定排序键,先按子集长度的负值排序(实现降序),同长度的子集按元素降序后的元组排序,确保最终结果符合降序要求。
  • 效率提升:相比生成所有子集再筛选,剪枝操作能大幅减少需要处理的子集数量,尤其是当阈值较小时,效率提升非常明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:05:21