Java 为什么我们要在一些递归算法中复制ArrayList?

Java 为什么我们要在一些递归算法中复制ArrayList?,java,algorithm,arraylist,Java,Algorithm,Arraylist,给定可能包含重复项S的整数集合,返回所有可能的子集 注: 比如说,, 如果S=[1,2,2],则解决方案为: [ [2], [1], [1,2,2], [2,2], [1,2], [] ] 答案是: public class Solution { public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) { ArrayList<ArrayList<

给定可能包含重复项S的整数集合,返回所有可能的子集

注:

比如说,, 如果S=[1,2,2],则解决方案为:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]
答案是:

public class Solution {
   public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
       ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
       ArrayList<Integer> tmp = new ArrayList<Integer>();
       Arrays.sort(num);
       sub(num, 0, tmp, ans);
       return ans;        
   }

   public void sub(int[] num, int k, ArrayList<Integer> tmp, ArrayList<ArrayList<Integer>> ans) {
       ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
       ans.add(arr);       

       for (int i = k; i < num.length; i++) {
           if (i != k && num[i] == num[i-1]) continue;

           tmp.add(num[i]);
           sub(num, i+1, tmp, ans);
           tmp.remove(tmp.size()-1);
       }
   }
}

直接添加它将使arr包含/成为与tmp相同的
ArrayList
实例。在您的循环中,当您更改tmp时,您也将更改arr,这不是您想要的过程。

直接添加它将使arr包含/成为与tmp相同的
ArrayList
实例。在循环中,当您更改tmp时,您也会更改arr,这不是您想要的过程。

如果您只想打印结果,因为您删除了递归调用后添加的任何元素,
tmp
在函数的开始和结束处看起来应该完全相同,因此,它不应该有任何区别(您的方式会更好,因为它不会在每个步骤复制
ArrayList

但是,当您将结果添加到
ans
时,问题就出现了

如果你用你的方式,只有一个
ArrayList
浮动-你只需将它添加到
ans
多次

请注意,将它添加到
ans
实际上并不创建它的副本,它只是将对
ArrayList
的引用添加到
ans
。因此,在添加原始文件后更改原始文件也会更改
ans
的元素


.

如果您只想打印结果,因为您删除了递归调用后添加的任何元素,
tmp
在函数的开始和结束处应该看起来完全相同,所以它不会有任何区别(您的方式会更可取,因为它不会在每个步骤复制
ArrayList

但是,当您将结果添加到
ans
时,问题就出现了

如果你用你的方式,只有一个
ArrayList
浮动-你只需将它添加到
ans
多次

请注意,将它添加到
ans
实际上并不创建它的副本,它只是将对
ArrayList
的引用添加到
ans
。因此,在添加原始文件后更改原始文件也会更改
ans
的元素

.

不使用的原因

 ans.add(tmp);
因为tmp是一个方法参数,所以java通过值传递对ArrayList的引用。 所以
tmp
实际上是对列表的引用,而不是列表

因此,您需要使用创建ArrayList对象,并将该对象添加到
ans

ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
ans.add(arr);   
ArrayList arr=新的ArrayList(tmp);
ans.add(arr);
如果您使用
ans.add(tmp)
,则tmp指向的arrayList将添加到ans中,并且如果稍后在代码中对
tmp
进行了任何修改,则添加到
ans
中的元素的内容也将更改,因为两者都指向同一个内存块

所以不使用

 ans.add(tmp);
因为tmp是一个方法参数,所以java通过值传递对ArrayList的引用。 所以
tmp
实际上是对列表的引用,而不是列表

因此,您需要使用创建ArrayList对象,并将该对象添加到
ans

ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
ans.add(arr);   
ArrayList arr=新的ArrayList(tmp);
ans.add(arr);

如果您使用
ans.add(tmp)
,则tmp指向的arrayList将添加到ans中,并且如果稍后在代码中对
tmp
进行了任何修改,则添加到
ans
中的元素的内容也将更改,由于两者都指向同一个内存块

您是否尝试了您认为应该是的内容并检查了发生了什么?您是否尝试了您认为应该是的内容并检查了发生了什么?
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
ans.add(arr);