Lintcode地址:http://www.lintcode.com/zh-cn/problem/subsets/
样例:
如果 S = [1,2,3],有如下的解:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
常规思路:递归添加元素,元素有出现和不出现2种状态,用1个数组保存该状态:
public List<List<Integer>> subsets(int[] nums) {
int len = nums.length;
boolean[] marks = new boolean[len];
List<List<Integer>> result = new ArrayList<>();
addSub(result, nums, marks, 0, len);
return result;
}
private void addSub(List<List<Integer>> result, int[] nums, boolean[] marks, int start, int len) {
if (start >= len) {
List<Integer> subList = new ArrayList<>();
for (int i = 0; i < len; i++) {
if (marks[i]) {
subList.add(nums[i]);
}
}
result.add(subList);
} else {
marks[start] = true;
addSub(result, nums, marks, start + 1, len);
marks[start] = false;
addSub(result, nums, marks, start + 1, len);
}
}
在网上看到了另一种更简洁的算法,用二进制整数各位的值表示元素是否出现的状态,循环加1该整数即可输出所有子集。
public List<List<Integer>> subsets(int[] nums) {
int len = nums.length;
List<List<Integer>> result = new ArrayList<>();
// 子集总数为2的len次幂
for (int k = 0; k < (1 << len); k++) {
List<Integer> sub = new ArrayList<>();
for (int j = 0; j < len; j++) {
// 第j位为1表示对应的数字出现在子集中
if (((k >> j) & 1) == 1) {
sub.add(nums[j]);
}
}
result.add(sub);
}
return result;
}
网友评论