问题描述:
Given a set of distinct integers, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
示例:
For example,
If nums = [1,2,3]
, a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
问题来源:Subsets (详细地址:https://leetcode.com/problems/subsets/description/)
思路分析:离散数学中给出的求解子集的个数是:2^n(n为数组中元素的个数),但是在程序中如何求解呢?答案就是采用回溯法(Backtracking),可能有很多人比较清楚了,因为Leetcode此类题目还是蛮多的,比如前面介绍的Combination Sum 系列(包括Combination Sum ,Combination Sum II ,Combination Sum III),还有Permutations系列,Palindrome Partitioning等等,采用的思想都是回溯,在这摘录了一段discuss中别人的一段话:
Backtracking can be solved always as follows:
Pick a starting point.
while(Problem is not solved)
For each path from the starting point.
check if selected path is safe, if yes select it
and make recursive call to rest of the problem
before which undo the current move.
End For
If none of the move works out, return false, NO SOLUTON.
翻译一下就是:首先我们选择一个入口,
while(问题没有得到解决)
For 从上面的入口开始,对于我们可以走的每一条路
我们都需要确认它是否是可行的,如果是的话那么就选择它
接着我们递归地解决掉这个问题
最后,我们取消掉当前这一步。
End For
如果我们没有可行的办法,那就返回false.
下面会到这道题本身,我们看看如何构造回溯,我们这的入口点就是先把空的list添加进结果当中,接着我们构造非空的list,暂时先将第一个元素添加进去,构造以第一个元素为开始的所有的子集,具体操作是我们尝试着第二个元素,第三个元素...直到没有办法添加数组中的元素了,接着我们就回溯,因为这条路已经走不通了,我们就回溯,回到还能添加进元素的那一步,知道当前索引已经添加完为止;接着索引往后移动,添加以当前元素开头的所有子集(即第二个元素开头的子集)........直到最后一个元素也添加完了。
代码: