描述
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
样例
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
挑战
你可以同时用递归与非递归的方式解决么?
思路
典型的dfs,但是没那么容易想清楚树的结构。在做无重复的permutation的时候,其实bfs、dfs都可以。但是要想清楚的是树的层次不是一个元素的选择作为一层(两枝分别为选和不选),而是真正加入了一个元素的时候作为一层。比如[1,2,2]和[1,2,3]中2和3在同一层。是同一个结点的后继。
去重的思路是对于重复的元素,只加入第一个,剩下的全部跳过。这时候可能会考虑比如在[1,2,2,2,3]的情境下,[2,2,2,3]是怎么出来的。因为对于第二个2来说,它的位置一定在第一个2的后面,所以它和3是同级的。因为第三个2必须在第二个2选了之后才能选,所以第三个2是第二个2的后继,不在当前考虑范围内。
因此第一个2的枝丫只能是第二个2,和除了2之外未被选择的数。这样问题就解决了。
(p.s 我觉得这道题对dfs的要求很高,理解必须非常深入才行)
代码
class Solution {
public:
/**
* @param nums: A set of numbers.
* @return: A list of lists. All valid subsets.
*/
vector<vector<int>> ans;
void dfs( int startPos, vector<int> &nums, vector<int>& subset )
{
ans.emplace_back(subset); //no choose
for( int i=startPos; i<nums.size(); ++i )
{
if( i!=startPos && nums[i] == nums[i-1] )
{
continue;
}
subset.emplace_back( nums[i] );
dfs( i+1, nums, subset );
subset.erase( subset.begin() + subset.size()-1 );
}
}
vector<vector<int>> subsetsWithDup(vector<int> &nums) {
// write your code here
vector<int> subset;
if( nums.size() == 0 )
{
ans.emplace_back(subset);
return ans;
}
sort(nums.begin(), nums.end());
dfs( 0, nums, subset );
return ans;
}
};