Java 为什么我们要在一些递归算法中复制ArrayList?
给定可能包含重复项S的整数集合,返回所有可能的子集 注: 比如说,, 如果S=[1,2,2],则解决方案为: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<
[
[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);