http://oj.leetcode.com/problems/subsets-ii/
给定可能包含重复项的整数集合S,返回所有可能的子集。
注意:
* Elements in a subset must be in non-descending order.
* The solution set must not contain duplicate subsets.
例如, 如果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);
}
}
}
我不知道为什么
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);
ans.add(arr);
但不是直接:
ans.add(tmp);
答案 0 :(得分:2)
直接添加它将使arr包含/与tmp相同的ArrayList
实例。在你的循环中,当你改变tmp时,你也会改变arr,这不是你想要的程序。
答案 1 :(得分:2)
如果您只想打印出结果,因为删除了在递归调用后添加的任何元素,tmp
在函数的开头和结尾都应该看起来完全一样,所以它不应该' t会有所不同(因为它不会在每一步都复制ArrayList
,所以你会喜欢你的方式。)
但是当您将结果添加到ans
时会出现问题。
如果您按照自己的方式使用,只会有一个ArrayList
浮动 - 您只需将其多次添加到ans
。
请注意,将其添加到ans
实际上并不创建它的副本,只是添加了对ArrayList
到ans
的引用。因此,在添加原始文件后更改原始文件也会更改ans
的元素。
答案 2 :(得分:1)
不使用
的原因 ans.add(tmp);
由于tmp是一个方法参数,因此java按值传递对ArrayList的引用。
所以tmp
实际上是对List的引用,而不是List。
因此,您需要创建一个ArrayList对象,并将该对象添加到ans
ArrayList<Integer> arr = new ArrayList<Integer>(tmp);
ans.add(arr);
如果你使用ans.add(tmp)
,那么tmp指向的arrayList将被添加到ans中,如果稍后在代码中对tmp
进行了任何修改,那么你的元素的内容添加到ans
也会更改,因为两者都会指向相同的内存块。