NC27 集合的所有子集(一) (回溯)
集合的所有子集(一)
https://www.nowcoder.com/practice/c333d551eb6243e0b4d92e37a06fbfc9
1.题目
描述
现在有一个没有重复元素的整数集合S,求S的所有子集 注意: 你给出的子集中的元素必须按升序排列
给出的解集中不能出现重复的元素
数据范围:1≤n≤5,集合中的任意元素满足∣val∣≤10
要求:空间复杂度 O(n!),时间复杂度 O(n!)
示例1
输入:
[1,2,3]
返回值:
[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
示例2
输入:
[]
复制
[]
2. 题解
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class S76 {
static ArrayList<ArrayList<Integer>> result = new ArrayList<>();
/**
* 该递归函数完成后,result中是: 在 arr 中 选择k个数字的全部组合(无重复)。
* 例如arr[]={1,2,3} 那么当backtracking(2,0,new ArrayList(),arr) 调用返回后 result={{1,2},{1,3},{2,3}};
*
* @param k 选择k个数字的组合
* @param start 从数组的 start位置 开始
* @param list 一个组合
* @param arr 原数组
*/
public static void backtracking(int k, int start, List<Integer> list, int[] arr) {
if (k < 0)
return;
else if (k == 0) {
//k==0表示已经找到了k个数字的组合,这时候加入全局result中
result.add(new ArrayList(list));
} else {
for (int i = start; i < arr.length; i++) {
list.add(arr[i]);
//上一行代码选择了一个数字 , 接着对于剩余数字 做组合。 k-1 表示接下来少选一个数,i+1表示 从数组的i+1开始
backtracking(k - 1, i + 1, list, arr);
// 去掉 arr[i] , 下一轮循环跳过这个数。 数组内每一个元素 都有两种状态:选或者不选。
list.remove(list.size() - 1);
}
}
}
/**
* 循环执行 backtracking 选择有 0 ,1 ,2, 3.....arr.length 个元素的组合 ,就构成了arr的所有子集(无重复)
*/
public static ArrayList<ArrayList<Integer>> subsets(int[] S) {
for (int i = 0; i <= S.length; i++) {
//选择i个数的组合
backtracking(i, 0, new ArrayList<>(), S);
}
return result;
}
public static void main(String[] args) {
int[] ints = {1, 2, 3, 4};
subsets(ints);
}
}