第一种:回溯解法
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> answer=new ArrayList<>();
if (nums == null || nums.length == 0) {
return answer;
}
subsetsCore(nums,0,answer,new ArrayList<>());
return answer;
}
public void subsetsCore(int[] nums, int index, List<List<Integer>> answer, List<Integer> currentAns) {
answer.add(new ArrayList<>(currentAns));
for(int i=index;i<nums.length;i++){
currentAns.add(nums[i]);
subsetsCore(nums,i+1,answer,currentAns);
currentAns.remove(currentAns.size()-1);
}
}
第二种:暴力解法
从[]解集开始,扫描一遍元素,每扫描到一个元素就添加到当前所有解里面,同时原有解保持不变。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> output = new ArrayList();
output.add(new ArrayList<Integer>());
for (int num : nums) {
List<List<Integer>> newSubsets = new ArrayList();
for (List<Integer> curr : output) {
newSubsets.add(new ArrayList<Integer>(curr){{add(num);}});
}
for (List<Integer> curr : newSubsets) {
output.add(curr);
}
}
return output;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode/
来源:力扣(LeetCode)
第三种:递归解法
对元素的选择可以构成一颗二叉树,树根为第一个元素,左子树代表解集包含当前结点,右子树代表解集不包含当前结点,第二层是第二个元素...etc。从树的根结点向下递归搜索,即可获得所有子集。
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> answer=new ArrayList<>();
if (nums == null || nums.length == 0) {
return answer;
}
subsetsCore(nums,0,answer,new ArrayList<>());
return answer;
}
public void subsetsCore(int[] nums, int index, List<List<Integer>> answer, List<Integer> currentAns) {
if(index>=nums.length){
//最终将结果构建叶子结点存储到解集
answer.add(new ArrayList<>(currentAns));
return;
}
//这一步是为了构建中间结点,避免多个递归过程中修改同一个对象
List<Integer> currentAnsTmp=new ArrayList<>(currentAns);
subsetsCore(nums,index+1,answer,currentAnsTmp);
currentAnsTmp.add(nums[index]);
subsetsCore(nums,index+1,answer,currentAnsTmp);
}
第四种:二进制映射方法求解
因为含有n个元素的集合的子集,正好相当于n个bit随机填充0或1的所有情况,也就是[0,2^n-1)的所有数值,每一个数值表示一个子集,数值bit为1表示元素在子集中。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> output = new ArrayList();
int n = nums.length;
for (int i = (int)Math.pow(2, n); i < (int)Math.pow(2, n + 1); ++i) {
// generate bitmask, from 0..00 to 1..11
String bitmask = Integer.toBinaryString(i).substring(1);
// append subset corresponding to that bitmask
List<Integer> curr = new ArrayList();
for (int j = 0; j < n; ++j) {
if (bitmask.charAt(j) == '1') curr.add(nums[j]);
}
output.add(curr);
}
return output;
}
}
来源:LeetCode