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

最优解需求:从指定列表选1-10个可重复元素求和等于目标值

高效解法:贪心+剪枝回溯(速度优先)

思路

要实现速度优先的解决方案,我们不需要枚举所有可能的组合,只需找到第一个符合条件的结果即可。核心优化点如下:

  • 优先选大元素:将数组反转成降序,优先尝试大数值元素,快速缩小目标值target,减少所需元素数量,同时满足最多选10个的限制。
  • 提前边界过滤:直接排除不可能的场景,比如target小于数组最小元素(1),或大于10个最大元素的总和(10*6498=64980),直接返回undefined。
  • 剪枝优化:遍历过程中跳过无效分支:
    • 当前元素大于剩余目标值时直接跳过;
    • 若剩余可用位置全选当前元素仍凑不够剩余目标值,直接跳过后续更小元素(降序排列,更小元素更无法满足)。
  • 立即返回结果:一旦找到符合条件的组合,立即终止计算并返回,避免不必要的遍历。

实现代码

const list = [
    1,
    3,
    6,
    8,
    12,
    18,
    25,
    28,
    30,
    40,
    45,
    50,
    60,
    68,
    78,
    88,
    98,
    128,
    158,
    198,
    248,
    298,
    348,
    418,
    488,
    548,
    588,
    618,
    648,
    698,
    798,
    818,
    848,
    898,
    998,
    1048,
    1098,
    1148,
    1198,
    1248,
    1298,
    1398,
    1448,
    1498,
    1598,
    1648,
    1998,
    2298,
    2598,
    2998,
    3298,
    3998,
    4498,
    4998,
    5898,
    6498,
];

// 预处理:转为降序数组,优先尝试大元素
const sortedDescList = [...list].reverse();

function getCombinations(
    list: number[],
    target: number
): Array<number> | undefined {
    const minVal = list[list.length - 1];
    const maxVal = list[0];
    // 边界情况快速过滤
    if (target < minVal || target > 10 * maxVal) {
        return undefined;
    }

    // 回溯函数:剩余目标值、已选元素、当前遍历起始索引
    const backtrack = (remainingTarget: number, path: number[], startIndex: number): number[] | undefined => {
        // 找到有效组合:和为target,元素数量1-10
        if (remainingTarget === 0) {
            if (path.length >= 1 && path.length <= 10) {
                return path;
            }
            return undefined;
        }
        // 元素数量超过10,直接剪枝
        if (path.length >= 10) {
            return undefined;
        }

        for (let i = startIndex; i < sortedDescList.length; i++) {
            const num = sortedDescList[i];
            // 当前元素大于剩余目标值,跳过(降序排列,后续更小无需遍历)
            if (num > remainingTarget) {
                continue;
            }
            // 剪枝:剩余位置全选当前元素也凑不够目标值,跳过
            const remainingSlots = 10 - path.length;
            if (num * remainingSlots < remainingTarget) {
                continue;
            }

            // 选择当前元素,继续回溯
            const result = backtrack(remainingTarget - num, [...path, num], i);
            // 找到结果立即返回,终止递归
            if (result) {
                return result;
            }
        }

        return undefined;
    };

    return backtrack(target, [], 0);
}

测试示例

console.log(getCombinations(list, 10)); // 输出 [8,1,1](或其他有效组合)
console.log(getCombinations(list, 20)); // 输出 [18,1,1] 或 [12,8]
console.log(getCombinations(list, 0)); // 输出 undefined
console.log(getCombinations(list, 100000)); // 输出 undefined

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:45:33