题目描述:给定一个可包含重复数字的序列,返回所有不重复的全排列。
题目地址:https://leetcode-cn.com/problems/permutations-ii/
思路:
1、设置first参数为当前位置,其左边是已加入队列的元素,右边是待加入的元素,当队列总元素等于数组的总元素时需要判断当前结果集是否有与队列元素排列一样的列表,有则不加入,无则加入。
2、优化思路1中的判断,将数组排序,那么此时可能出现重复的列表发生在当前元素等于前一个元素的值,并且前一个元素已经进行过排列,此时需要跳过当前元素,进行剪枝。
代码展示:
1、
/**
* @ClassName Solution
* @Description
* @Author Administrator
* @Date 2020/6/6 14:05
* @Version 1.0
**/
class Solution {
List<List<Integer>> lists = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
if(nums == null || nums.length == 0)
return lists;
ArrayList<Integer> list = new ArrayList<>();
for (int temp : nums)
list.add(temp);
find(list, 0);
return lists;
}
public void find(ArrayList list, int first){
if(first == list.size()){
ArrayList<Integer> temp = new ArrayList<>(list);
boolean flag = true;
for(int i = 0; i < lists.size(); i++){
int j, k;
for(j = 0, k = 0; j < lists.get(i).size() && k < temp.size() && lists.get(i).get(j) == temp.get(k); j++, k++);
if(j == k && k == temp.size()){
flag = false;
break;
}
}
if(flag)
lists.add(temp);
} else {
for(int i = first; i < list.size(); i++){
Collections.swap(list, first, i);
find(list, first + 1);
Collections.swap(list, first, i);
}
}
}
}
2、
/**
* @ClassName Solution1
* @Description
* @Author Administrator
* @Date 2020/6/6 14:29
* @Version 1.0
**/
public class Solution {
List<List<Integer>> lists = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
if(nums == null || nums.length == 0)
return lists;
boolean[] flags = new boolean[nums.length];
Arrays.sort(nums);
Deque<Integer> deque = new ArrayDeque<>();
find(nums, flags, deque);
return lists;
}
public void find(int[] nums, boolean[] flags, Deque deque){
if(deque.size() == nums.length){
lists.add(new ArrayList<>(deque));
}else {
for(int i = 0; i < nums.length; i++){
if(flags[i])
continue;
if(i > 0 && nums[i] == nums[i - 1] && !flags[i - 1])
continue;
flags[i] = true;
deque.add(nums[i]);
find(nums, flags, deque);
deque.removeLast();
flags[i] = false;
}
}
}
}