JS实现PowerSum算法:子集数组拼接问题求助
解决PowerSum算法的子集收集问题
我懂你现在的困境——能打印出符合条件的子集,但就是没法把这些子集整合到一个二维数组里返回对吧?这在递归回溯类算法里是新手常踩的坑,咱们一步步来解决它。
先给你一个能正确收集所有有效子集的PowerSum实现,咱们边看代码边拆解关键点:
function powerSum(X, N) { // 先生成所有不超过X的自然数N次幂,作为候选元素 const candidates = []; let num = 1; while (Math.pow(num, N) <= X) { candidates.push(Math.pow(num, N)); num++; } // 用来存储所有符合条件的子集 const validSubsets = []; // 回溯核心函数:currentSum当前累加和,start起始索引(避免重复子集),currentSubset当前正在构建的子集 function backtrack(currentSum, start, currentSubset) { // 找到符合条件的子集,存入结果(注意要拷贝数组,不然后续修改会影响已存入的内容) if (currentSum === X) { validSubsets.push([...currentSubset]); return; } // 当前和已经超过X,直接剪枝返回,不用继续递归 if (currentSum > X) { return; } // 从start开始遍历,保证子集元素按顺序选取,避免重复组合(比如[1,9]和[9,1]算同一种) for (let i = start; i < candidates.length; i++) { const value = candidates[i]; // 选择当前元素加入子集 currentSubset.push(value); // 递归:累加当前值,起始索引改为i+1(不能重复用同一个自然数) backtrack(currentSum + value, i + 1, currentSubset); // 回溯:撤销选择,把元素从子集里移除 currentSubset.pop(); } } // 初始调用:从0和为空的子集开始 backtrack(0, 0, []); // 返回二维数组形式的所有有效子集,要数量的话直接return validSubsets.length即可 return validSubsets; } // 测试示例:X=10,N=2,应该返回[[1,9]] console.log(powerSum(10, 2)); // X=100,N=2,返回[[100], [36,64], [1,9,16,25,49]] console.log(powerSum(100, 2));
你大概率踩过的几个坑:
- 没有拷贝子集数组:如果直接
validSubsets.push(currentSubset),因为数组是引用类型,后续回溯的pop操作会把已经存入结果的数组也修改掉,必须用[...currentSubset]或者currentSubset.slice()创建副本再存入。 - 递归时没控制起始索引:如果每次递归都从0开始遍历候选元素,会生成重复的子集(比如[1,9]和[9,1]),所以要从当前索引的下一个位置开始,保证子集按顺序生成,避免重复计数。
- 没正确合并递归结果:如果你的
subsetSum函数是返回单个子集或局部结果数组,那需要把递归返回的结果展开合并到全局的子集数组里,而不是只做打印操作。 - 缺少剪枝逻辑:当当前累加和已经超过X时,直接停止递归,能大幅提升算法效率,避免不必要的计算。
要是你有自己写的代码片段,也可以贴出来,咱们能更精准地定位问题~
内容的提问来源于stack exchange,提问作者Monique
相关产品推荐
相关产品推荐

