Given a set of distinct integers, nums, return all possible subsets (the power set).
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], [] ]
void genSubsets(vector<vector<int>>& res, vector<int>& cur, vector<int>& nums, int pos) {
res.push_back(cur);
for (int i = pos; i < nums.size(); i++) {
cur.push_back(nums[i]);
genSubsets(res, cur, nums, i + 1);
cur.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
vector<int> cur;
genSubsets(res, cur, nums, 0);
return res;
}
代码和之前的 permutation / combination 非常相似,事实上递归解题方法中的递归题都非常相似。不同的题目的区别在于:1. 何时将cur保存进结果 2. 何时return 3. 下一次递归传入什么样的参数 。这题中,1. 每次进入genSubsets都相当于走到遍历树上的一个节点,此时都进行一次 res.push_back(cur); 2. 深度遍历下去一直到没有候选元素就return,即pos指向nums的最后一个数;3. 下一次递归的nums中不应该有之前出现过的数字,所以下一次开始遍历的pos比当前pos大1.
(2) 迭代
This problem can also be solved iteratively. Take [1, 2, 3] in the problem statement as an example. The process of generating all the subsets is like:
// Initially: [[]]
// Adding the first number to all the existed subsets: [[], [1]];
// Adding the second number to all the existed subsets: [[], [1], [2], [1, 2]];
// Adding the third number to all the existed subsets: [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]].
代码:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> subs(1, vector<int>());
for (int i = 0; i < nums.size(); i++) {
int n = (int)subs.size();
for (int j = 0; j < n; j++) {
subs.push_back(subs[j]); // copy a new subs[j]
subs.back().push_back(nums[i]); // expand the just being created subs[j] with nums[i]
}
}
return subs;
}
每次先将已有的项拷贝一个出来,然后在其上追加当前遍历到的nums[i]。
两种方法都可以,我只想到了第一种,因为在我的印象里我都是按照第一种方法求subsets的。当然看到迭代的写法时才意识到可以这样求subsets,然后按照这个思路的代码就是顺其自然的事了。