package highFrequencyLeetcode.leetcode_78; import java.util.ArrayList; import java.util.List; /** *

* * 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 * * 说明:解集不能包含重复的子集。 * * 示例: * * 输入: nums = [1,2,3] * 输出: * [ * [3], *   [1], *   [2], *   [1,2,3], *   [1,3], *   [2,3], *   [1,2], *   [] * ] * *

* * @author Seina * @version 2019-06-26 20:31:22 */ public class Subsets { /** * 解法1 递归 * * @param nums: 不含重复元素的整数数组 * @return 所有子集 */ public List> subsets(int[] nums) { List> ans = new ArrayList>(); getAns(nums, 0, new ArrayList(), ans); return ans; } /** * * 递归填充结果集合 ans * * ans 和 temp 的树形变化 : [1] [2] [3] * / \ | * [12] [13] [23] * / * [123] * * * temp 的增长变化 : a: [1] e: [2] g: [3] * / \ | * b: [2] d: [3] f: [3] * / * c: [3] * * 举例说明: * * 比如 a -> b -> c 开始递归调用到 c: [3],它的下一层递归将 [123] 存进去就结束了 * * 然后当前所在层的递归也就结束了,就开始执行 temp.remove,移掉 [3] * * 然后递归 b: [2] 陆续结束,开始移掉 [2],然后循环控制继续走递归 a: [1] 的另一部分,递归调用 d: [3] * * 以此类推,简单变化过程如下图: * * * a: [1] a: [1] a: [1] a: [1] a: [1] * -> / -> / -> / -> \ * b: [2] b: [2] b: [2] d: [3] * / * c: [3] * * @param nums: 题目给定数组 * @param start: 开始指针 * @param temp: 可以理解成结果集合里面的子集 * @param ans: 结果集合 */ private void getAns(int[] nums, int start, ArrayList temp, List> ans) { //将子集添加到结果集合中 ans.add(new ArrayList(temp)); for (int i = start; i < nums.length; i++) { temp.add(nums[i]); //从 start + 1 开始,递归下坠到后面的元素 getAns(nums, i + 1, temp, ans); //每次递归调用结束将加入到 temp 的元素删除 temp.remove(temp.size() - 1); } } /** * 解法2 位运算解决 * * @param nums: 不含重复元素的整数数组 * @return 所有子集 */ public static List> subsets2(int[] nums) { List> ans = new ArrayList>(); for (int i = 0; i < (1 << nums.length); i++) { List sub = new ArrayList(); for (int j = 0; j < nums.length; j ++) if (( (i >> j) & 1 ) == 1) sub.add(nums[j]); ans.add(sub); } return ans; } }