47. 全排列 II

全排列 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++;
                        }
                    }
                }
            }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值