其他分享
首页 > 其他分享> > 回溯day5

回溯day5

作者:互联网

46. 全排列

class Solution {
    private List<List<Integer>> res;
    private LinkedList<Integer> path;
    public List<List<Integer>> permute(int[] nums) {
        res = new ArrayList<>();
        path = new LinkedList<>();
        if (nums.length == 0 || nums == null) return res;
        else if (nums.length == 1) {
            path.add(nums[0]);
            res.add(new ArrayList<>(path));
            return res;
        }
        backtracking(nums);
        return res;
    }
    private void backtracking(int[] nums) {
        int len = nums.length;
        //最小子问题 排两个
        if (len == 2) {
            path.add(nums[0]);
            path.add(nums[1]);
            res.add(new ArrayList<>(path));
            path.removeLast();
            path.removeLast();

            path.add(nums[1]);
            path.add(nums[0]);
            res.add(new ArrayList<>(path));
            path.removeLast();
            path.removeLast();
        }
        for (int i = 0; i < len; i++) {
            //不断细化成子问题 直到子数组长度为2就是最小子问题
            int[] descendant = new int[len - 1];
            int j = 0;
            //当前作为头的数不是原数组nums第一个元素 需要将其前面所有元素添加到子需排列数组中
            if (i > 0) {
                for (; j < i; j++) {
                    descendant[j] = nums[j];
                }
            }
            //nums下标i以后的数加入子数组。
            for (; j < len - 1; j++) {
                descendant[j] = nums[j + 1];
            }
            path.add(nums[i]);
            backtracking(descendant);
            path.removeLast();
        }
    }
}

这里是通过new一个子数组descendant排除已排元素,亦可以定义一个used数组存已经用过的数,代码会更加简洁。

class Solution {
    private List<List<Integer>> res;
    private LinkedList<Integer> path;
    private int len;
    private boolean used[];
    public List<List<Integer>> permute(int[] nums) {
        res = new ArrayList<>();
        path = new LinkedList<>();
        len = nums.length;
        used = new boolean[len];
        if (len == 0 || nums == null) return res;
        backtracking(nums);
        return res;
    }
    private void backtracking(int[] nums) {
        if (len == path.size()) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < len; i++) {
            //使用used数组判断元素是否被使用过
            if (used[i]) continue;
            path.add(nums[i]);
            used[i] = true;
            backtracking(nums);
            path.removeLast();
            used[i] = false;
        }
    }
}

47. 全排列 II

class Solution {
    private List<List<Integer>> res;
    private LinkedList<Integer> path;
    private boolean[] used;
    private int len;
    public List<List<Integer>> permuteUnique(int[] nums) {
        res = new ArrayList<>();
        len = nums.length;
        if (len == 0 || nums == null) return res;
        path = new LinkedList<>();
        used = new boolean[len];
        backtracking(nums);
        return res;
    }
    private void backtracking(int[] nums) {
        if (len == path.size()) {
            res.add(new ArrayList<>(path));
            return;
        }
        Set<Integer> hashSet = new HashSet<>();
        for (int i = 0; i < len; i++) {
            //子处理中跳过已使用的数 同层次去重
            if (used[i] || hashSet.contains(nums[i])) continue;
            hashSet.add(nums[i]);
            used[i] = true;
            path.add(nums[i]);
            backtracking(nums);
            path.removeLast();
            used[i] = false;
        }
    }
}

也可以使用used数组去重,i > 0 && nums[i] == nums[i - 1]  && used[i-1] == false表示同层树已经使用过(在循环中), used[i-1] == true表示在同一树枝中使用过(在递归中)。

class Solution {
    private List<List<Integer>> res;
    private LinkedList<Integer> path;
    private boolean[] used;
    private int len;
    public List<List<Integer>> permuteUnique(int[] nums) {
        res = new ArrayList<>();
        len = nums.length;
        if (len == 0 || nums == null) return res;
        path = new LinkedList<>();
        used = new boolean[len];
        Arrays.sort(nums);
        backtracking(nums);
        return res;
    }
    private void backtracking(int[] nums) {
        if (len == path.size()) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < len; i++) {
            //同层次去重 used[i] == false表示,使用i元素在前一个树枝同一层使用过且处理完毕
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                used[i] = false;
                continue;
            }
            //子处理中跳过已使用的数 
            if (used[i]) continue;
            used[i] = true;
            path.add(nums[i]);
            backtracking(nums);
            path.removeLast();
            used[i] = false;
        }
    }
}

 

参考:programmercarl.com

标签:used,nums,res,day5,len,回溯,path,new
来源: https://www.cnblogs.com/lizihhh/p/backtracking05.html