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

递归生成数组子集时全局集合存储空列表的问题咨询

递归生成数组子集时全局集合存储空列表的问题咨询

嗨,我来帮你捋清楚这个问题~你猜的没错,这确实和Java里的引用传递特性直接相关!

咱们来拆解下你代码里的问题根源:

  • 你在整个递归过程中只用了一个ans对象,每次递归传递的都是这个对象的引用,而不是它的副本。
  • 当递归走到终止条件i >= arr.length时,你执行pow.add(ans),这一步只是把ans的引用存到了pow里,并没有把当时ans里的元素复制一份存进去。
  • 递归结束后你会执行回溯操作(ans.remove(ans.size()-1)),等整个递归流程跑完,ans会被一步步回溯成空列表。而pow里的所有元素都是指向同一个ans的引用,所以最后打印pow时,看到的全是空列表;但递归过程中打印ans是当时的实时状态,所以是正确的。

那怎么解决呢?给你两种常用的方案:

方案一:在终止条件中添加ans的副本(推荐,效率更高)

修改终止条件里的代码,每次添加到pow时,新建一个ArrayList来复制当前ans的元素,这样存到pow里的就是独立的列表了:

if(i >= arr.length){
    System.out.println(ans); // 仍会打印正确的当前状态
    // 新建列表并复制当前ans的元素,再添加到pow
    pow.add(new ArrayList<>(ans));
    return;
}

方案二:递归调用时传递ans的副本

这种方式会在每次递归分支时都创建新的列表副本,虽然能解决问题,但因为频繁创建对象,效率不如方案一:

private static void powset(int[] arr, int i, ArrayList<Integer> ans) {
    if(i >= arr.length){
        System.out.println(ans);
        pow.add(ans);
        return;
    }
    // 包含当前元素的分支:创建新副本添加元素后传递
    ArrayList<Integer> includeAns = new ArrayList<>(ans);
    includeAns.add(arr[i]);
    powset(arr,i+1,includeAns);
    
    // 不包含当前元素的分支:直接传递新副本
    ArrayList<Integer> excludeAns = new ArrayList<>(ans);
    powset(arr,i+1,excludeAns);
}

把代码改成方案一的样子,再运行就能看到pow正确输出所有子集啦~

备注:内容来源于stack exchange,提问作者Uddeshya Seth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:02:47