lintcode 中等题:subSets 子集

时间:2023-03-08 21:35:25

题目

子集

给定一个含不同整数的集合,返回其所有的子集

样例

如果 S = [1,2,3],有如下的解:

[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
注意

子集中的元素排列必须是非降序的,解集必须不包含重复的子集

挑战

你可以同时用递归与非递归的方式解决么?

解题

根据上面求排列的思想很类似,还是深度优先遍历。由于输出每个子集需要升序,所以要先对数组进行排序。求出所以的子集,也就是求出所以的组合方式 + 空集

问题转化为求组合方式的问题

参考链接不仅要考虑起始位置,还需要考虑长度,这样才是组合 C(n,k),由于我只想到要考虑起始位置,而长度问题在程序中增加,一直没有解决问题

核心程序

    public void helper(int[] nums,int start,int len,
ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
if( list.size() == len){
res.add(new ArrayList<Integer>(list));
return;
}
for(int i=start;i< nums.length;i++){
if(list.contains(nums[i])){
continue;
}
list.add(nums[i]);
helper(nums,i+1,len,list,res);
list.remove(list.size()-1);
} }
class Solution {
/**
* @param S: A set of numbers.
* @return: A list of lists. All valid subsets.
*/
public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
// write your code here
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(nums == null || nums.length ==0)
return res;
Arrays.sort(nums); res.add(list);
for(int len = 1;len<= nums.length;len++){
helper(nums,0,len,list,res); }
return res;
}
public void helper(int[] nums,int start,int len,
ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
if( list.size() == len){
res.add(new ArrayList<Integer>(list));
return;
}
for(int i=start;i< nums.length;i++){
if(list.contains(nums[i])){
continue;
}
list.add(nums[i]);
helper(nums,i+1,len,list,res);
list.remove(list.size()-1);
} }
}

Java Code

九章中程序进行了优化,长度不考虑,递归一次list的值都是子集的一个元素

class Solution {
/**
* @param S: A set of numbers.
* @return: A list of lists. All valid subsets.
*/
public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
// write your code here
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(nums == null || nums.length ==0)
return res;
Arrays.sort(nums);
helper(nums,0,list,res); return res;
}
public void helper(int[] nums,int start, ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
res.add(new ArrayList<Integer>(list));
for(int i=start;i< nums.length;i++){
if(list.contains(nums[i])){
continue;
}
list.add(nums[i]);
helper(nums,i+1,list,res);
list.remove(list.size()-1);
} }
}

Java Code

class Solution:
"""
@param S: The set of numbers.
@return: A list of lists. See example.
"""
def subsets(self, S):
def dfs(depth, start, valuelist):
res.append(valuelist)
if depth == len(S): return
for i in range(start, len(S)):
dfs(depth+1, i+1, valuelist+[S[i]])
S.sort()
res = []
dfs(0, 0, [])
return res

Python Code

根据位运算进行求解

        // 1 << n is 2^n
// each subset equals to an binary integer between 0 .. 2^n - 1
// 0 -> 000 -> []
// 1 -> 001 -> [1]
// 2 -> 010 -> [2]
// ..
// 7 -> 111 -> [1,2,3]

下面是我自己实现

class Solution {
/**
* @param S: A set of numbers.
* @return: A list of lists. All valid subsets.
*/
public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
// write your code here
int len = nums.length;
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(nums == null || len==0)
return res;
Arrays.sort(nums);
// 1 << n is 2^n
// each subset equals to an binary integer between 0 .. 2^n - 1
// 0 -> 000 -> []
// 1 -> 001 -> [1]
// 2 -> 010 -> [2]
// ..
// 7 -> 111 -> [1,2,3]
for(int i=0;i< 1<<len ;i++){
ArrayList<Integer> list = new ArrayList<Integer>();
// 检测哪一位是 1
int n = i;
for(int j=0;j< len;j++){
if(n%2==1)
list.add(nums[j]);
n=n/2;
}
res.add(list);
}
return res;
}
}

九章中判断第几位是1的程序如下:

 for (int i = 0; i < (1 << n); i++) {
ArrayList<Integer> subset = new ArrayList<Integer>();
for (int j = 0; j < n; j++) {
// check whether the jth digit in i's binary representation is 1
if ((i & (1 << j)) != 0) {
subset.add(nums[j]);
}
}
result.add(subset);
}

是懂非懂,好像这样也可以判断第几位是1

class Solution:
"""
@param S: The set of numbers.
@return: A list of lists. See example.
"""
def subsets(self, nums):
# write your code here
res = []
size = len(nums)
nums.sort()
if nums == None or size == 0:
return res
for i in range(1<<size):
lst=[]
n = i
for j in range(size):
if n%2==1:
lst.append(nums[j])
n/=2
res.append(lst)
return res

Python Code