LeetCode排列问题:JavaScript递归回溯函数返回空数组原因排查
回溯求解排列时返回空数组的原因与修复方案
问题核心原因
你的代码出现「控制台打印正确但最终返回空数组」的问题,根源在于数组引用的误用:
推入栈的引用而非副本
当执行ans.push(stack)时,你推入的是stack数组的内存引用,而非当前栈内容的独立副本。后续递归中的stack.pop()会直接修改这个引用指向的数组内容。当整个回溯流程结束后,stack被清空回初始的空数组,ans里所有元素其实都是指向同一个空数组的引用,最终返回结果自然是[[]]。
你控制台能打印正确结果,是因为打印操作发生在push之后、pop之前,此时栈内的排列内容还未被修改。多余的
ans.indexOf(stack)判断
数组属于引用类型,indexOf比较的是引用地址是否相同。递归过程中stack始终是同一个数组引用,所以ans.indexOf(stack)永远返回-1,会重复推入同一个引用,但这不是返回空数组的核心原因,完全可以移除该判断(回溯逻辑本身不会生成重复排列)。
修复后的代码
只需要修改push操作,推入当前栈内容的副本即可:
/** * @param {number[]} nums * @return {number[][]} */ var permute = function(nums) { let s = [], a = []; return findPerm(nums, s, a); }; var findPerm = function(nums, stack, ans){ if(nums.length === stack.length){ ans.push([...stack]); // 推入栈的浅拷贝副本,避免引用共享 console.log(ans); return; // 提前返回,减少不必要的循环 } for(let num of nums){ if(stack.indexOf(num) === -1){ stack.push(num); findPerm(nums, stack, ans); stack.pop(); } } return ans; }; permute([1,2,3]);
补充说明
- 除了
[...stack],也可以用stack.slice()或Array.from(stack)来创建数组副本,效果一致。 - 移除多余的
indexOf判断后,代码逻辑更简洁,且不会影响结果正确性——因为回溯过程中每个排列只会被生成一次。
内容的提问来源于stack exchange,提问作者Will Sherman
相关产品推荐
相关产品推荐

