以下两题剪枝的条件都是,如果当前元素为1或者当前元素等于前面的元素,那么前面那个元素还没有出现过,则当前这个元素也不能出现。
//C++
class Solution {
public:
vector<vector<int>>ans;//回溯+去重
vector<int>temp;
int hash[10];
void dfs(vector<int>nums,int dep){
if(dep == nums.size()){
ans.push_back(temp);
return;
}
for(int i=0;i<nums.size();i++){
/*
hash[i]:当前数字是否出现过
* 如果当前数字与前一个数字相同(nums[i] == nums[i - 1]),
* 并且前一个数字还没有出现的话(vis[i - 1] == false),
* 那么就不能选择当前数字(continue),
* 如果前面的数字已经出现过(vis[i] == true),则可以,总之相邻重复出现的元素,只能够前一个元素出现,后一个元素才能出现,这样就保证了唯一性。
* 选择当前数字
*/
if(hash[i] || (i > 0 && nums[i] == nums[i - 1] && !hash[i - 1]))continue;
hash[i]=1;
temp.push_back(nums[i]);
dfs(nums,dep+1);
temp.pop_back();
hash[i]=0;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
memset(hash,0,sizeof(hash));
sort(nums.begin(),nums.end());
dfs(nums,0);
return ans;
}
};
//JAVA
class Solution {
List<String>ans = new ArrayList<>();
StringBuilder temp = new StringBuilder();
public void dfs(char[] arr,int n,int[] visted){
if(temp.length() == n){
ans.add(temp.toString());
}
for(int i=0;i<n;i++){
if(visted[i] == 1||(i>0&&arr[i] == arr[i-1]&&visted[i-1]==0))continue;//对于相邻且相同的元素,只有当前一个元素出现后,这个元素可以出现。
visted[i]=1;
temp.append(arr[i]);
dfs(arr,n,visted);
visted[i]=0;
temp.deleteCharAt(temp.length()-1);
}
}
public String[] permutation(String S) {
char[] arr = S.toCharArray();
Arrays.sort(arr);
int n = S.length();
int[] visted = new int[n];
dfs(arr,n,visted);
return ans.toArray(new String[ans.size()]);
}
}