回溯法
核心思想: 与LeetCode第四十六题的核心思想一致,只是需要增加去重操作,去重的方式为:先对数组nums[]进行排序,使得nums[]中的相同元素在相邻位置,并规定相同元素只能从左到右逐个填入空格即可。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> resList = new ArrayList<>();//结果集
List<Integer> res = new ArrayList<>();//排列组合
int count = 0;//已填数字的空格个数,count=nums.length表示空格已填满
boolean[] used = new boolean[nums.length];//标记数组,用于标记数组nums[]中的数字是否已使用
Arrays.sort(nums);//对数组nums[]进行排序
getResultListUnique(nums, resList, res, count, used);//回溯法求所有的排列组合
return resList;
}
//回溯法求所有的排列组合
void getResultListUnique(int[] nums, List<List<Integer>> resList, List<Integer> res, int count, boolean[] used){
if(count == nums.length){//空格已填满
resList.add(new ArrayList<>(res));//注意:先对res当前的内容进行拷贝,再加入结果集(因为res一开始为空,其内容在回溯过程一直改变,最后也为空)
return;
}
for(int i = 0; i < nums.length; i++){//寻找数组nums[]中尚未使用过的数字
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {//去重操作
continue;
}
res.add(nums[i]);//构建排列组合
used[i] = true;//已使用
getResultListUnique(nums, resList, res, count + 1, used);//递归构建排列组合
res.remove(res.size() - 1);//撤销空格填入的数字
used[i] = false;//撤销标记数组used[]的对应标记
}
}
}