持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
一文学会用程序求解子集
给你一个整数数组(其实可以将其看做是一个集合),让你求解出这个集合的所有子集,对于这个问题,如果让大家用笔做的话,肯定很快就做出来了,可是你们知道怎么用程序来解决这个问题吗?
下面咱们就一起来学习一下究竟应该怎样用程序来解决这个问题!
算法分析
在写程序之前,我们首先需要明白一个点,那就是什么是集合的子集? 集合的子集就是有集合里的元素组成的,包含空集以及它自身;所以算法需要做的就是将这里面的每一个可能都以对应结果的形式返回。
算法实现
定义两个全局变量:
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
递归回溯算法:
private void backTracing(int startIndex, int[] nums) {
result.add(new ArrayList<>(path));
/**
* 一般是像组合问题那样,有明确的几个数为一组才会有其他的终止条件
* 不然都是让 startIndex 走到最后num.length - 1
*/
if (startIndex >= nums.length) {
// result.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i < nums.length; i++) {
path.add(nums[i]);
// backTracing(startIndex + 1, nums);
backTracing(i + 1, nums);
path.remove(path.size() - 1);
}
}
对回溯的一个总结:
将子结果添加到最终结果中:
如果是组合问题的话,这个语句应该放在递归终止条件的判断里面的, 但是因为现在是子集问题,所以放在了递归终止条件的前面
组合问题 和 子集问题的区别:
组合问题是有一个数量限制的,比如 2个数为一组 【1,2,3】中 【1,2,】【1,3】 【2,3】 子集问题,如【1,2,3】的子集可以是 【】 【1】【1,2】【1,2,3】 【2】【2,3】 【3】 将下面这个语句放在终止条件的前面,就可以得到了每一次选数的过程结果,这里对应的就是子集 组合问题之所以要放在终止判断里面,是因为它要够数了才能走 而子集问题不同,子集问题只要有来的就可以走
主函数:
public List<List<Integer>> subsets(int[] nums) {
if (nums == null) {
return result;
}
backTracing(0, nums);
return result;
}
这里的主函数就是一个调用回溯算法的一个过程。