全排列 II
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路+代码+注释:
public class FourSeven {
public static void main(String[] args) {
permuteUnique(new int[]{1,1,2});
}
public static List<List<Integer>> permuteUnique(int[] nums) {
/*
思路:1.对数组进行排序,如果访问到的元素的后面的元素和该元素相同,那么往后推到
等于该元素的最后一个元素的位置——解决数据重复问题
2.因为确定一个位置的数后,下一个位置不能再使用该数,所以定义一个visited访问
数组,该数组和nums数组一样大,用来标记nums数组中的元素是否被访问
3.还是采用递归的方式,确定一个位置的数后递归确认下一个位置的数
4.递归终止条件,当位置大于要确定的元素个数时,证明都找完了不用找了
*/
Arrays.sort(nums);
int weiZhi=1;
//out用来存储找到的元素组合
List<Integer> out=new ArrayList<>(nums.length);
List<List<Integer>> result=new ArrayList<List<Integer>>();
int[] visited=new int[nums.length];
queRenWeiZhi(nums,visited,1,out,result);
return result;
}
private static void queRenWeiZhi(int[] nums,int[] visited,int weiZhi,List<Integer> out,List<List<Integer>> result)
{
//终止条件
if (weiZhi>nums.length)
{
//这时候需要将out的数据放到新集合中存到结果里
result.add(new ArrayList<Integer>(out));
}else {
for (int i = 0; i < nums.length; i++) {
//判断元素是否被前面访问过
if (visited[i]==0)
{
//确定一个位置
out.add(nums[i]);
//将该位置赋值为1,代表被访问过
visited[i]=1;
queRenWeiZhi(nums,visited,weiZhi+1,out,result);
//下一个位置确认完后,该元素就可以放开了
visited[i]=0;
//该位置确认完后移除,避免对下一个组合有影响
out.remove(out.size()-1);
//判断后面的元素是否和该元素相同,相同就往后推
while (i<nums.length-1 && nums[i]==nums[i+1])
{
i++;
}
}
}
}
}
}