https://leetcode.com/problems/subsets/#/description
问题描述:给定一个没有重复元素的数组求所有子集。
Given a set of distinct integers, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
思路解析:
假设一个序列有n个元素
一个序列子集的个数为2^n,而这个数字也等于由这n个数能组成的所有二进制数的个数,
例如[8,9],则n=2,可以组成的二进制数
00
01
10
11
所以这个思想可以对应到求子集合的问题上来,还有1的那一列就对应着序列中的相应位置上的数字
[]
[9]
[8]
[8,9]
就酱~
主要问题是如何用代码的形式表述出这个二进制数的推理过程?
移位运算符
1<< n
相当于n是几就左移几位,如果放到循环当中,for(i = 0;i < n; i++) 1<< n; 此时假设n=3
0 0 1
0 1 0
1 0 0
这三种情况
依次与子集合的index(二进制数)做“与”操作的话就相当于判断寻找该子集所代表的二进制数哪位是1(按位查找)
public class Solution {
public List<List<Integer>> subsets(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result=new ArrayList<List<Integer>>();
//元素的个数
int n=nums.length;
//子集的个数
int total=1<<n;
for(int i=0;i<total;++i)
{
List<Integer> temp=new ArrayList<Integer>();
for(int j=0;j<n;j++)
{
if( ((1<<j)&i) !=0)
{
temp.add(nums[j]);
}
}
result.add(temp);
}
return result;
}
}
第二种方法,递归
public class Solution {
public List<List<Integer>> subsets(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result=new ArrayList<>();
getSubset(result,new ArrayList<>(),nums,0);
return result;
}
public void getSubset(List<List<Integer>> result,List<Integer> temp,int[] nums,int pos)
{
result.add(new ArrayList<>(temp));
for(int i=pos;i<nums.length;i++)
{
temp.add(nums[i]);
getSubset(result,temp,nums,i+1);
temp.remove(temp.size()-1);
}
}
}