题目描述:
解题思路:
之前博客总结过全排列的写法,就是一个递归,交换元素就行了,但是总结的方法是不含有重复元素的全排列,这道题,给的元素是重复的,所以需要稍微的修改一下。
含有重复元素的全排列,主要就是在理解了一般的全排列后,思考去除或者叫剪枝,方法很多。
有两种方法,先说第一种吧,声明一个list,在进行排列的时候将第一个交换的元素放入,然后之后判断的时候,如果已经包含了这个元素,就不进行全排列,这个思路是看这里理解的。
直接给出代码吧。
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> lists=new ArrayList<>();
qpl(0,nums,lists);
return lists;
}
void qpl(int begin,int[] nums,List<List<Integer>> lists)
{
List<Integer> exit=new ArrayList<>();
if(begin==nums.length)
{
List<Integer> list=new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
list.add(nums[i]);
}
lists.add(list);
return;
}
for (int i = begin; i <nums.length ; i++) {
if(!exit.contains(nums[i]))
{
exit.add(nums[i]);
swap(nums,i,begin);
qpl(begin+1,nums,lists);
swap(nums,i,begin);
}
}
}
private void swap(int[] nums, int i, int begin) {
int temp=nums[i];
nums[i]=nums[begin];
nums[begin]=temp;
}
另一种方法是蓝桥杯视频里面讲解的一种方法,抓取理解,但是要先事先排好序,感觉没有第一种方法好理解,也没第一种方法方便,下面也给出代码。
class Solution {
public static List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);//首先排序,有序的才可以
List<List<Integer>> lists=new ArrayList<>();
boolean[] vis=new boolean[nums.length];
int[] path=new int[nums.length];
dfs(nums,0,path,vis,lists);
return lists;
}
static void dfs(int[] nums,int n,int[] path,boolean[] vis,List<List<Integer>> lists){
if(n==nums.length)
{
List<Integer> list=new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
list.add(path[i]);
}
lists.add(list);
return;
}
for (int i = 0; i < nums.length; i++) {
//和上一个元素相同,而且上一个元素没有被访问过
if(i>0&&nums[i]==nums[i-1]&&!vis[i-1])
{
continue;//不抓取
}
if(!vis[i])
{
vis[i]=true;
path[n]=nums[i];
dfs(nums,n+1,path,vis,lists);
vis[i]=false;
}
}
}
}