leetcode刷题6
今天刷的题是LeetCode的第78题,子集。题目的要求是:给定一个不含相同元素的数组,要求输出所有的子集。该题也是没有思路,看的别人的答案写的代码
目前通过参阅别人的解答思路,掌握了两种比较好的解决方法。第一种是位运算。这个解决方法很有意思,就是每个元素其实都是两种状态,在子集中和不在子集中,那么对应的是二进制中的1和0。一个包含n个元素的数组,其子集的个数为2的n次方。将数字转化为二进制,位为1的添加到子集中。如下思路所示。
* 1 2 3
* 0 0 0 -> [ ]
* 0 0 1 -> [ 3]
* 0 1 0 -> [ 2 ]
* 0 1 1 -> [ 2 3]
* 1 0 0 -> [1 ]
* 1 0 1 -> [1 3]
* 1 1 0 -> [1 2 ]
* 1 1 1 -> [1 2 3]
具体的代码如下所示:
public static List<List<Integer>> binaryBit(int[] nums) { /** * 位操作:数组中的元素,有两个状态,在子数组中和不在子数组中。1代表在,0代表不在 * 1 2 3 * 0 0 0 -> [ ] * 0 0 1 -> [ 3] * 0 1 0 -> [ 2 ] * 0 1 1 -> [ 2 3] * 1 0 0 -> [1 ] * 1 0 1 -> [1 3] * 1 1 0 -> [1 2 ] * 1 1 1 -> [1 2 3] */ List<List<Integer>> res = new ArrayList<List<Integer>>(); int len=1<<nums.length; for (int i = 0; i < len; i++) { List<Integer> sub = new ArrayList<Integer>(); for (int j = 0; j < nums.length; j++) if (((i >> j) & 1) == 1) { sub.add(nums[j]); } res.add(sub); } return res; }
第二个解决方法也很巧妙。首先考虑问题规模很小的情况,当只有一个元素时,其子集分别是本身和空集。当两个元素时,分别在原有子集的基础上,添加该元素,再新增子集。具体的代码如下所示:
public static List<List<Integer>> leetcode78(int[] nums){ // 如果将问题缩小到一个元素,那么就是两种情况,空集合本身 // 此时,再挨个往子集里添加新的元素 List<List<Integer>> result=new ArrayList<>(); int n = nums.length; result.add(new ArrayList<>()); for (int i = 0; i <n ; i++) { int length=result.size(); for (int j = 0; j <length ; j++) { List<Integer> list=new ArrayList<>(result.get(j)); list.add(nums[i]); result.add(list); } } return result; }