47.全排列II

47.全排列II_第1张图片

自己解法

这题解法和全排列类似,只用对同层相同的分支进行剪枝,有点忘了在哪剪了,还是放在后面剪比较好理解,回溯完以后,判断同层有没有相同的。

class Solution {

    private List> output = new ArrayList<>();

    public List> permuteUnique(int[] nums) {

        if (nums.length == 0) {

            return output;

        }

        Arrays.sort(nums);

        boolean[] used = new boolean[nums.length];

        List res = new ArrayList<>(nums.length);

        dfs(nums, used, res, nums.length);    

        return output;

    }

    public void dfs(int[] nums, boolean[] used, List res, int n) {

        if (res.size() == n) {

            output.add(new ArrayList(res));

            return;            

        }

        for (int i = 0; i < n; i++) {

            if (!used[i]) {

                res.add(nums[i]);

                used[i] = true;

                dfs(nums, used, res, n);

                used[i] = false;

                res.remove(res.size() - 1);

                // 剪枝,减去同层重复的内容

                while (i < (n - 1) && nums[i] == nums[i+1]) {

                    i++;

                }       

            }

        }

    }

}

官方解法

这种解法是前置剪枝的,首先,当前节点是没有使用过的,不然没意义,然后和前一个节点进行比较,如果和回溯过的前一个点相同,则跳过当前点。

import java.util.ArrayDeque;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Deque;

import java.util.List;

public class Solution {

    public List> permuteUnique(int[] nums) {

        int len = nums.length;

        List> res = new ArrayList<>();

        if (len == 0) {

            return res;

        }

        // 排序(升序或者降序都可以),排序是剪枝的前提

        Arrays.sort(nums);

        boolean[] used = new boolean[len];

        // 使用 Deque 是 Java 官方 Stack 类的建议

        Deque path = new ArrayDeque<>(len);

        dfs(nums, len, 0, used, path, res);

        return res;

    }

    private void dfs(int[] nums, int len, int depth, boolean[] used, Deque path, List> res) {

        if (depth == len) {

            res.add(new ArrayList<>(path));

            return;

        }

        for (int i = 0; i < len; ++i) {

            if (used[i]) {

                continue;

            }

            // 剪枝条件:i > 0 是为了保证 nums[i - 1] 有意义

            // 写 !used[i - 1] 是因为 nums[i - 1] 在深度优先遍历的过程中刚刚被撤销选择

            if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {

                continue;

            }

            path.addLast(nums[i]);

            used[i] = true;

            dfs(nums, len, depth + 1, used, path, res);

            // 回溯部分的代码,和 dfs 之前的代码是对称的

            used[i] = false;

            path.removeLast();

        }

    }

    public static void main(String[] args) {

        Solution solution = new Solution();

        int[] nums = {1, 1, 2};

        List> res = solution.permuteUnique(nums);

        System.out.println(res);

    }

}

你可能感兴趣的:(47.全排列II)