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

如何实现将整数数组拆分为两个等长等和子集的ArrayChallenge函数?

问题分析

这是带长度限制的子集和问题,核心约束有三个:

  • 选出的子集长度严格等于原数组长度的一半
  • 选出的子集元素总和等于原数组总和的1/2
  • 最终输出要排序后按首元素大小顺序拼接两个子集
实现步骤
  • 首先计算原数组总和,如果总和为奇数,直接返回空(无合法解)
  • 计算目标子集和target = 总和 / 2,目标子集长度k = arr.length / 2
  • 回溯搜索符合长度和总和要求的子集,可加剪枝优化提升效率:
    • 当前已选元素个数超过k直接终止
    • 当前已选元素总和超过target直接终止
    • 剩余未选元素全部加进来也凑不够k个直接终止
  • 找到合法子集后,将剩余元素归为另一个子集
  • 两个子集分别做升序排序,比较首元素,首元素更小的子集放在前面
  • 把两个子集的元素按顺序拼接成逗号分隔的字符串即可
代码实现(JavaScript版本)
function ArrayChallenge(arr) {
    const total = arr.reduce((a, b) => a + b, 0);
    // 总和为奇数直接无解
    if (total % 2 !== 0) return '';
    const target = total / 2;
    const k = arr.length / 2;
    let resSubset = null;

    // 回溯找符合条件的子集
    function backtrack(start, currentSum, currentList) {
        if (currentList.length === k) {
            if (currentSum === target) {
                resSubset = [...currentList];
                return true;
            }
            return false;
        }
        // 剪枝:剩余元素不够凑k个
        if (currentList.length + (arr.length - start) < k) return false;
        // 剪枝:当前和已经超过target
        if (currentSum > target) return false;

        for (let i = start; i < arr.length; i++) {
            currentList.push(arr[i]);
            if (backtrack(i + 1, currentSum + arr[i], currentList)) return true;
            currentList.pop();
            // 跳过重复元素避免重复搜索
            while (i < arr.length - 1 && arr[i] === arr[i + 1]) i++;
        }
        return false;
    }

    // 先排序原数组提升剪枝效率
    arr.sort((a, b) => a - b);
    backtrack(0, 0, []);
    if (!resSubset) return '';

    // 统计频率筛选另一个子集
    const freq = {};
    resSubset.forEach(num => freq[num] = (freq[num] || 0) + 1);
    const otherSubset = arr.filter(num => {
        if (freq[num]) {
            freq[num]--;
            return false;
        }
        return true;
    });

    // 两个子集排序后按首元素顺序拼接
    resSubset.sort((a, b) => a - b);
    otherSubset.sort((a, b) => a - b);
    const finalArr = resSubset[0] < otherSubset[0] ? [...resSubset, ...otherSubset] : [...otherSubset, ...resSubset];
    return finalArr.join(',');
}

// 测试示例
console.log(ArrayChallenge([16,22,35,8,20,1,21,11])); // 输出 1,11,20,35,8,16,21,22
优化说明
  • 提前对原数组排序,可以让剪枝更高效,提前排除超过target的分支
  • 跳过重复元素的优化可以避免大量重复搜索,大幅提升存在重复元素时的运行效率
  • 找到第一个合法子集就直接返回,不需要遍历所有可能,减少不必要的计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:48:02