第一種:回溯解法
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