LeetCode ---- 47、全排列 II

题目链接

思路:

此题的思路与46题全排列一致,只是在处理过程中需要排除掉重复的排列,这是因为所给数组中存在着重复的数字。

首先需要给数组排序,以便将重复的值都排在相邻的位置,这样进行去重的时候就会方便很多。

在回溯算法中去重时,若当前位置的数等于前一个位置的数,并且前一个位置的数没有使用过(这块没有使用过是因为在之前的回溯中已经被撤销了选择,实际上在之前的回溯中已经使用过了,为了避免重复,故需要不相等的数才行),那么就应该跳过这个数,进行下一个数的搜索。

    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        if (nums == null || nums.length < 1) {
            return ans;
        }
        Arrays.sort(nums);
        boolean[] used = new boolean[nums.length];
        dfs(nums, 0, used, new ArrayList<Integer>(), ans);
        return ans;
    }
    private void dfs(int[] nums, int depth, boolean[] used, 
                                List<Integer> path, List<List<Integer>> ans) {
        if (depth == nums.length) {
            ans.add(new ArrayList<Integer>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            // 若当前位置的数等于前一个位置的数,并且前一个位置的数没有使用过
            // 这块没有使用过是因为在之前的回溯中已经被撤销了选择,
            // 实际上在之前的回溯中已经使用过了,为了避免重复,
            // 故需要不相等的数才行
            if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
                continue;
            }
            // 若当前数没有被使用过
            if (!used[i]) {
                // 选择当前数
                used[i] = true;
                path.add(nums[i]);
                // 寻找下一个位置的数
                dfs(nums, depth + 1, used, path, ans);
                // 撤销选择
                used[i] = false;
                path.remove(path.size() - 1);
            }
        }
    }

思路及代码参考自:https://leetcode-cn.com/problems/permutations-ii/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liwe-2/

猜你喜欢

转载自blog.csdn.net/sinat_34679453/article/details/106506522