DFS和回溯专题:全排列 II

    DFS和回溯专题:全排列 II

题目链接: 全排列 II

参考题解 代码随想录

题目描述

在这里插入图片描述

代码纯享版

class Solution {

    public List<List<Integer>> list_all = new ArrayList();
    public List<Integer> list = new ArrayList();
    public int[] res;
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        res = new int[nums.length];
        backtrack(nums);
        return list_all;
    }

    void backtrack(int[] nums){

        if(list.size() == nums.length){
            list_all.add(new ArrayList(list));
            return;
        }


        for(int i = 0; i < nums.length; i++){
            if(i > 0 && nums[i] == nums[i - 1] && res[i - 1] == 0){
                continue;
            }
            if(res[i] == 0){
                list.add(nums[i]);
                res[i] = 1;
                backtrack(nums);
                res[i] = 0;
                list.remove(list.size() - 1);
            }
            
        }
    }
}

代码逐行解析版

class Solution {

    public List<List<Integer>> list_all = new ArrayList();
    public List<Integer> list = new ArrayList();
    public int[] res; 

    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums); //先对数组nums进行sort排序
        res = new int[nums.length]; //数组res用来判断对应位置的数是否用过:0为没用,1为用过
        backtrack(nums);
        return list_all;
    }

    void backtrack(int[] nums){

        if(list.size() == nums.length){ //如果list列表长度与nums数组长度相同
            list_all.add(new ArrayList(list)); //将list添加到list_all
            return;
        }


        for(int i = 0; i < nums.length; i++){

            //剪枝:nums[i]==nums[i-1]而res[i-1]为0,
            //说明同一树层上有两个重复的元素nums[i)和nums[i-1],不可以重复选取      
            if(i > 0 && nums[i] == nums[i - 1] && res[i - 1] == 0){ 
                continue;
            }
            if(res[i] == 0){ //res[i]未被使用
                list.add(nums[i]); //将该数字添加到list列表中
                res[i] = 1; //将该数字标记为已使用过

                backtrack(nums); //递归
                //将列表list的最后一个数字去掉,同时还原标记
                res[i] = 0;
                list.remove(list.size() - 1);
            }
            
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值