解法:回溯算法
class Solution {
private:
vector<vector<int>> res; //保存结果
void backtrack(vector<int>& nums,int start){
if(nums.size()==start){ //满足结束条件
res.push_back(nums);
return;
}
set<int> s;
for(int i=start;i<nums.size();i++){
if(s.count(nums[i]))
continue;
swap(nums[i],nums[start]); //做选择
backtrack(nums,start+1);
swap(nums[i],nums[start]); //撤销选择
s.insert(nums[i]);
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
backtrack(nums,0);
return res;
}
};
优化:枝剪
class Solution {
private:
vector<vector<int>> res;
void backtrack(vector<int>& track,vector<int> nums,vector<bool>& used){
if(track.size() == nums.size()){ //满足条件
res.push_back(track);
return;
}
for(int i=0; i<nums.size(); i++){
//当前值用过了 或 当前值等于前一个值: 两种情况:
//1 nums[i-1] 没用过 说明回溯到了同一层 此时接着用num[i] 则会与 同层用num[i-1] 重复
//2 nums[i-1] 用过了 说明此时在num[i-1]的下一层 相等不会重复
if(used[i] || (i>0 && !used[i-1] && nums[i] == nums[i-1])) //枝剪
continue;
track.push_back(nums[i]); //做选择
used[i] = true;
backtrack(track,nums,used);
track.pop_back(); //撤销选择
used[i] = false;
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end()); //排序
vector<int> track; //路径
vector<bool> used(nums.size(), false); //判断是否被选择过
backtrack(track,nums,used); //参数:路径,选择列表,选择约束
return res;
}
};