给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
这道题与全排列不一样的是去重复。所以要判断到底访问过没有
//基本难点就是要去掉重复的
//以这个[1,1,2]为例
//正常会返回6个结果:其中第一行是以下标为0的1开始,而第二行是以下标为1的1开始。
//1,1,2;1,2,1
//1,1,2;1,2,1
//2,1,1;2,1,1
//去重做法就是,在dfs时要判断i和i-1是否相等和i-1这个值是否被用。
//相等和没有被用就跳过这个i的情况,直接去i+1判断。
//因为没被用的话,之后就可以再用这个i-1,那就会出现重复的情况。
//比如说第二行是i=1时的判断,此时i和i-1的值相等,且i-1的值没被用
//那么跳过i=1这个情况,直接去i=2,所以我们就去掉了第二行所有重复的。
回溯法
public static List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length == 0) {
return lists;
}
//一定要排序
Arrays.sort(nums);
List<Integer> list = new ArrayList<>();
boolean[] visitlist = new boolean [nums.length];
dfs(nums,list,visitlist);
return lists;
}
private static void dfs(int[] nums,List<Integer> list,boolean[] visitlist){
if(list.size() ==nums.length){
lists.add(new ArrayList<>(list));
return;
}else {
for(int i =0;i<nums.length;i++){
if(visitlist[i]){
continue;
}
if(i > 0 && nums[i] == nums[i-1] && visitlist[i-1] ==false)
{
continue;
}
list.add(nums[i]);
visitlist[i] = true;
dfs(nums,list,visitlist);
list.remove(list.size()-1);
visitlist[i] = false;
}
}
}
主函数
public static void main(String[] args) {
System.out.println("请输入数字序列:");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] strs = str.substring(1,str.length()-1).split(",");
int[] nums = new int[strs.length];
for (int i = 0; i < strs.length; i++) {
nums[i] = Integer.parseInt(strs[i]);
}
List<List<Integer>> lists = permuteUnique(nums);
for(int i =0;i<lists.size();i++){
System.out.println(lists.get(i));
}
}
结果、