
本文详解 javascript 递归生成数组幂集(所有子集)时,因误传数组引用导致结果全为空数组的根本原因,并提供深拷贝临时数组的正确实现方案。
本文详解 javascript 递归生成数组幂集(所有子集)时,因误传数组引用导致结果全为空数组的根本原因,并提供深拷贝临时数组的正确实现方案。
在使用回溯法实现 LeetCode「子集」(Subsets)问题时,一个常见却隐蔽的陷阱是:将同一数组引用反复压入结果集合。上述代码看似逻辑正确——递归遍历每个元素,选择/不选择,到达边界时将当前路径 temp 推入 all_sets。但最终输出却是 [[],[],[],[],[],[],[],[]](对 [1,2,3,4] 得到 8 个空数组),而非预期的 [[1,2,3,4], [1,2,3], [1,2,4], ...]。
根本原因在于 JavaScript 中数组是引用类型。temp 始终是同一个数组对象的引用,而 all_sets.push(temp) 实际上是把该引用多次存入 all_sets。随着递归回溯执行 temp.pop(),temp 不断被修改、清空;当整个递归栈展开完毕后,all_sets 中所有元素都指向最终已变为空的 temp,因此打印时全部显示为空数组。
✅ 正确解法是在边界条件处创建 temp 的独立副本,而非引用:
function generate(nums, curr_index, temp, all_sets) {
if (curr_index === nums.length) {
all_sets.push([...temp]); // ✅ 使用扩展运算符创建浅拷贝
return;
}
temp.push(nums[curr_index]);
generate(nums, curr_index + 1, temp, all_sets);
temp.pop(); // 回溯:撤销选择
generate(nums, curr_index + 1, temp, all_sets);
}
function generateAllSubsets(nums) {
const all_sets = [];
generate(nums, 0, [], all_sets);
return all_sets;
}
console.log(generateAllSubsets([1, 2, 3]));
// 输出: [[1,2,3],[1,2],[1,3],[1],[2,3],[2],[3],[]]? 关键点说明:
立即学习“Java免费学习笔记(深入)”;
-
[...temp]利用扩展运算符生成temp的浅拷贝,适用于本题(元素为基本类型,如数字); - 若
nums包含对象或嵌套数组,需改用JSON.parse(JSON.stringify(temp))或结构化克隆(structuredClone(temp),现代环境支持); - 此模式也适用于其他回溯问题(如组合、排列、分割回文串等),核心原则始终是:结果收集时必须保存当前状态的快照,而非共享引用。
通过这一微小但关键的修改,即可确保每个子集作为独立数组被正确捕获,彻底解决“数组值不保留”的问题。


















