LeetCode HOT 100:子集(简单易懂的回溯)

2023-02-16,,,,

题目:78. 子集

题目描述:

给你一个整数数组,数组中元素互不相同。返回数组中所有可能的子集,且子集不能重复

什么是子集?举个例子:原数组[1, 2, 3][]、[1]、[1, 2]、[1, 3]、[1, 2, 3]、[2]、[2, 3]、[3]这些都是原数组的子集。所以说子集就是原数组中零个或几个元素组成的集合。而且,子集是无序的,[1, 2][2, 1]是同一个子集,所以说虽然[2, 1]也是原数组的子集,但是题目要求子集不能重复,所以不能在结果中一起出现。

思路:

其实这一题思路和组合总数或全排列很像,也是回溯。只不过每次递归的时候,不能像别的题可以从0开始穷举,那样会导致子集重复,所以要每次递归的时候,传入一个开始下标startIndex,这样就能避免子集重复问题。

步骤:

回溯模版可以看前面的全排列或者组合总数题目讲解,这里就不赘述。

本题主要是回溯方法怎么写,所以下面步骤是回溯方法的步骤。

1、先定义好回溯方法的入参,数组,本次递归穷举的开始下标

2、定义好回溯方法后,方法里首先确定回溯结束的条件

这一题可以不需要回溯结束条件。因为这一题本身就是中间状态的子集也需要收集,并没有说子集长度多少或者什么别的条件的时候才收集。而且不加回溯结束条件也不会导致无限递归,因为循环中,开始下标是不断增大的,等到开始下标达到数组长度的时候,自然循环终止!

3、下面就是开始穷举,伪代码如下

for (int i = startIndex; i < nums.length; i++) {
将元素放入数组
迭代回溯方法(传入的开始下标是 i + 1,因为下个迭代从 i + 1 开始遍历)
将元素从数组中删除,回溯
}

代码:

    List<List<Integer>> ans;
List<Integer> list; public List<List<Integer>> subsets(int[] nums) {
ans = new ArrayList<>();
list = new ArrayList<>(); process(nums, 0);
return ans;
} public void process(int[] nums, int startIndex) {
ans.add(new ArrayList<>(list)); // 子集不讲究顺序,所以[1,2]和[2,1]是同一子集
// 题目要求不能返回重复子集
// 所以 i 不能从 0 开始,要从 startIndex 开始。
// 这样才能保证不断往后找,不能回头找
for (int i = startIndex; i < nums.length; i++) {
list.add(nums[i]);
process(nums, i + 1);
list.remove(list.size() - 1);
}
}

LeetCode HOT 100:子集(简单易懂的回溯)的相关教程结束。

《LeetCode HOT 100:子集(简单易懂的回溯).doc》

下载本文的Word格式文档,以方便收藏与打印。