参考了以下的人终于搞懂了点
参考1
参考2
参考3
78 子集 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 说明:解集不能包含重复的子集。 Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solution set must not contain duplicate subsets.
/*思路1 * Backtracking+dfs * 回溯+深度优先搜索 * 如果要理解,看到一个解释,也可以当作:存在和不存在。 * 外层循环逐一往中间集合 temp 中加入元素 nums[i],使这个元素处于存在状态 * 开始递归,递归中携带加入新元素的 temp,并且下一次循环的起始是 i 元素的下一个,因而递归中更新 i 值为 i + 1 * 将这个从中间集合 temp 中移除,使该元素处于不存在状态 * */
public static List> subsets(int[] nums) {
Arrays.sort(nums);
List> res = new ArrayList<>();
List temp = new ArrayList<>();
dfs(res, temp, nums, 0);
return res;
}
/* * 再具体点 * 形如[1,2,3]得到 * [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]] * 假设某一步 temp=》 tempList.add(nums[i])=>[1] * 在进行dfs的时候是[1]add下一层=》[1,2]=>再下一层dfs->[1,2,3],结束后往上回溯remove 3 =>[1,2] * 继续回溯会变为remove 2 =>[1] 最外层remove 1 =》[] * 最最外层循环结束,i++,从num[1]=2开始=temp=>[2] * */
private static void dfs(List> list, List tempList, int[] nums, int start) {
list.add(new ArrayList<>(tempList));
for (int i = start; i < nums.length; i++) {
tempList.add(nums[i]);
dfs(list, tempList, nums, i + 1);
tempList.remove(tempList.size() - 1);
}
}
附带循环的思路
package Array.Medium;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*78 子集
* 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
* 说明:解集不能包含重复的子集。
* Given a set of distinct integers, nums, return all possible subsets (the power set).
* Note: The solution set must not contain duplicate subsets.
* */
public class Subsets {
/*思路1
* Backtracking+dfs
* 回溯+深度优先搜索
* 如果要理解,看到一个解释,也可以当作:存在和不存在。
* 外层循环逐一往中间集合 temp 中加入元素 nums[i],使这个元素处于存在状态
* 开始递归,递归中携带加入新元素的 temp,并且下一次循环的起始是 i 元素的下一个,因而递归中更新 i 值为 i + 1
* 将这个从中间集合 temp 中移除,使该元素处于不存在状态
* */
public static List> subsets1(int[] nums) {
Arrays.sort(nums);
List> res = new ArrayList<>();
List temp = new ArrayList<>();
dfs(res, temp, nums, 0);
return res;
}
/* * 再具体点
* 形如[1,2,3]得到
* [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]
* 假设某一步 temp=》 tempList.add(nums[i])=>[1]
* 在进行dfs的时候是[1]add下一层=》[1,2]=>再下一层dfs->[1,2,3],结束后往上回溯remove 3 =>[1,2]
* 继续回溯会变为remove 2 =>[1] 最外层remove 1 =》[]
* 最最外层循环结束,i++,从num[1]=2开始=temp=>[2]
* */
private static void dfs(List> list, List tempList, int[] nums, int start) {
list.add(new ArrayList<>(tempList));
for (int i = start; i < nums.length; i++) {
tempList.add(nums[i]);
dfs(list, tempList, nums, i + 1);
tempList.remove(tempList.size() - 1);
}
}
/*思路3
* 选和不选+二进制
* [ 1 , 2 , 3 ]
* f f f []
* t f f [1]
* t t f [1,2]
* ...类推
* */
/*思路2
* 遍历
* 出现新的,就把新的添加到上一层子集的后面
* 详解
* res的size是递增的
* 外层遍历每个nums的元素
* 内层遍历res的元素,被外层当前元素add进temp再add进res即可
* */
public static List> subsets(int[] nums) {
List> res = new ArrayList<>();
res.add(new ArrayList<>());
for (int num : nums) { // ①从数组中取出每个元素
int size = res.size();
for (int i = 0; i < size; i++) {
List temp = new ArrayList<>(res.get(i)); // ②逐一取出中间结果集
System.out.println(res.get(i));
temp.add(num); // ③将 num 放入中间结果集
res.add(temp); // ④加入到结果集中
}
}
return res;
}
public static void main(String[] args) {
int[] num = {1, 2, 3};
System.out.println(subsets(num));
}
}