【leetcode刷题笔记】Subsets II

Given a collection of integers that might contain duplicates, S, return all possible subsets.

Note:

  • Elements in a subset must be in non-descending order.
  • The solution set must not contain duplicate subsets.

For example,
If S = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

subsets这道题非常相像,除了S中会有重复的元素,那么会有什么影响呢?看一个例子:

S = [1,1]

根据subsets中的算法,生成的子集如下:

[
  [],
  [1],
  [1],
  [1,1]
]

显然[1],[1]这两个是重复的,需要去掉。那么我们怎么判重?只需要在递归函数的循环里面加上如下判断

 if(i != pos && s[i] == s[i - 1]) continue; 就可以了。

理解这个判断的关键,是搞清楚递归函数

public void subsetsDfs(int[] s,int level,int pos,ArrayList<Integer> result,List<List<Integer>> answer)

中pos变量的含义。

在这个函数中,level表示要生成的子集的长度,pos则表示目前要生成子集的第pos位上的元素。那么当i==pos的时候,说明子集中第pos位上的元素还没有生成过,那么即使s[i]==s[i-1],它们在生成的子集中所占有的位置不同(例如例子中的[1,1]中的两个1分别在生成的子集的第0位和第1位上),s[i]就可以加到这个子集上去。但是当i != pos的时候,说明生成的子集上第pos位已经有元素了,如果当前的s[i]和这个元素s[i-1]相等,那么就没有必要再在这个位置上重复放置s[i]了(例如上述例子中已经有子集[1]的时候,不能够再生成子集[s[1]=1]了)。

最后实现的代码如下:

 1 public class Solution {
 2     public void subsetsDfs(int[] s,int level,int pos,ArrayList<Integer> result,List<List<Integer>> answer){
 3         if(result.size() == level){
 4             answer.add(new ArrayList<Integer>(result));
 5             return;
 6         }
 7         for(int i = pos;i < s.length;i++){
 8             if(i != pos && s[i] == s[i - 1])
 9                 continue;                
10             result.add(s[i]);
11             subsetsDfs(s, level, i+1, result, answer);
12             result.remove(result.size()-1);
13         }
14     }
15     public List<List<Integer>> subsetsWithDup(int[] S) {
16         Arrays.sort(S);
17         List<List<Integer>> answer = new ArrayList<List<Integer>>();
18         ArrayList<Integer> result = new ArrayList<Integer>();
19         
20         for(int i = 0;i <= S.length;i++)
21             subsetsDfs(S, i, 0, result, answer);
22         return answer;
23     }
24 }
原文地址:https://www.cnblogs.com/sunshineatnoon/p/3858250.html