题目
代码(首刷看解析)
class Solution {
public:
vector<vector<int>> res;
vector<int> track;
vector<bool> used;
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end()); // 因为是全排列,所以排序了也不存在问题
used.resize(nums.size());
backtrack(nums);
return res;
}
void backtrack(vector<int>& nums) {
if(track.size() == nums.size()) {
res.push_back(track);
return;
}
for(int i = 0; i < nums.size(); i++) {
if(used[i]) continue;
if(i > 0 && nums[i] == nums[i-1] && used[i-1]) continue; // 防止重复,注意要添加!used[i-1],只有这样才会保证没有漏掉
track.push_back(nums[i]);
used[i] = true;
backtrack(nums);
track.pop_back();
used[i] = false;
}
}
};
代码(8.24 二刷看解析)
i > 0 && num[i] == num[i-1] && !used[i-1]
或者i > 0 && num[i] == num[i-1] && used[i-1]
:首先是为了防止相同的分支,而used
则是为了保留第一个或者最后一个分支,有区别,但答案都一样。!used[i]
是保留第一个分支。
class Solution {
public:
vector<vector<int>> res;
vector<int> used, tmp;
vector<vector<int> > permuteUnique(vector<int>& num) {
sort(num.begin(), num.end());
used.resize(num.size(), 0);
backtrack(num);
return res;
}
void backtrack(vector<int>& num) {
if(num.size() == tmp.size()) {
res.emplace_back(tmp);
return;
}
for(int i = 0; i < num.size(); i++) {
if(used[i]) continue;
if(i > 0 && num[i] == num[i-1] && !used[i-1]) { // 新添加的剪枝逻辑,固定相同的元素在排列中的相对位置
continue;
}
used[i] = 1;
tmp.emplace_back(num[i]);
backtrack(num);
used[i] = 0;
tmp.pop_back();
}
}
};
代码(10.1 三刷看解析)
class Solution {
public:
vector<int> tmp;
vector<int> used;
vector<vector<int>> res;
vector<vector<int>> permuteUnique(vector<int>& nums) {
used.resize(nums.size());
sort(nums.begin(), nums.end());
backtrack(nums);
return res;
}
void backtrack(vector<int>& nums) {
if(tmp.size() == nums.size()) {
res.emplace_back(tmp);
return;
}
for(int i = 0; i < nums.size(); i++) {
if(used[i]) continue;
if(i > 0 && nums[i] == nums[i-1] && used[i-1]) continue;
used[i] = 1;
tmp.emplace_back(nums[i]);
backtrack(nums);
used[i] = 0;
tmp.pop_back();
}
}
};