给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
分析:
如果没有“不重复”这个条件,本题就是一个简单的DFS,没有什么好说的。但是既然加上了这个条件,那么此题就变得略微复杂了一些。
我们可以考虑一下,在没有该条件的限制下,我们会产生两次[1, 1, 2],正是因为两个1之间有一个先后顺序,才导致了重复序列的产生。因此,为了能够产生不重复的全排列,可以考虑消除1之间的先后顺序,简而言之,也就是不管相同数字之间有多少种排列,我们只选择其中一种。既然要找相同数字,排列是一种不错的选择。在接下来的选择中,可以按照排序的顺序进行选择,比如有[1, 1', 1'', 2]四个数字,当程序要选1/1'/1''这个数字的时候,令其最先选1,然后选1'',当前面两个1都被选完之后,再选1''。
那么条件就是每次选择不同数字的第一个还未被使用的数字。当然也可以定义其他的顺序,或者说干脆用set来查重,就是很麻烦罢了。
class Solution {
public:
void dfs(vector<vector<int>> &ans, vector<int> &list, vector<int> &nums, int k, vector<int> &vis){
if(k == nums.size()){
ans.push_back(list);
return ;
}
for(int i = 0; i < nums.size(); i++){
//每次选择不同数字的第一个还未被使用的数字
if(!vis[i] && (i == 0 || nums[i] != nums[i - 1] || vis[i - 1])){
list.push_back(nums[i]);
vis[i] = 1;
dfs(ans, list, nums, k + 1, vis);
list.pop_back();
vis[i] = 0;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
vector<int> list;
vector<int> vis(nums.size(), 0);
dfs(ans, list, nums, 0, vis);
return ans;
}
};