一、题目
二、题解
在全排列1的基础上,全排列2要求结果集合中不能有重复,在进行dfs的时候就需要进行剪枝,比如序列【1 1 1 2】,首先枚举结果的每一个位置的情况,第一个位置可以是选择序列中0下标的1,那么序列中下标位1 2 的元素对于的也是1就不能选择了,如果第一个位置选择1,在选择第二个位置的时候序列中下标是0的1刚才被选做结果集合的第一个位置的元素因此不能选择,接着序列中下标是1的元素1是可以作为结果序列的第二个位置的值,接着序列中2下标对应的元素1,就不能作为结果序列的第二个位置元素了,因为结果序列的第二个位置已经选择过元素1了,此时不能选择,所以在进行dfs过程中需要进行两步的剪枝:1.已经选择过的元素不可在选择,通过全局的check数组可以解决 2. 当前位置上已经选择过的元素不能选择
class Solution {
public:
vector<vector<int>> res;
vector<int> path, nums;
int n;
bool check[10];
void dfs(int u) {
if (u == n) {
res.push_back(path);
return;
}
for (int i = 0; i < n; i++) {
// 如果当前元素被 选了 或者 当前元素等于前面一个元素且前面的元素没有没选那么这样就会发生重复,此时进行剪枝
if (check[i] || (i != 0 && (nums[i] == nums[i - 1] && !check[i - 1]))) continue;
path.push_back(nums[i]);
check[i] = true;
dfs(u + 1);
check[i] = false;
path.pop_back();
continue;
}
}
vector<vector<int>> permuteUnique(vector<int>& _nums) {
nums = _nums;
n = nums.size();
sort(nums.begin(), nums.end());
dfs(0);
return res;
}
};
class Solution {
List<List<Integer>> ans;
List<Integer> path;
int[] nums;
boolean check[];
int n;
void dfs(int u) {
if (u == n) {
ans.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < n; i++) {
if (i == 0 && !check[0]) {
path.add(nums[i]);
check[i] = true;
dfs(u + 1);
check[i] = false;
path.remove(path.size() - 1);
continue;
}
if (!check[i] && (i != 0 && nums[i] != nums[i-1] || !check[i - 1])) {
path.add(nums[i]);
check[i] = true;
dfs(u + 1);
check[i] = false;
path.remove(path.size() - 1);
}
}
}
public List<List<Integer>> permuteUnique(int[] _nums) {
nums = _nums;
Arrays.sort(nums);
n = nums.length;
ans = new ArrayList<>();
path = new ArrayList<>();
check = new boolean[n];
dfs(0);
return ans;
}
}