leetcode----47. Permutations II

链接:

https://leetcode.com/problems/permutations-ii/

大意:

给定一个含重复元素值的数组nums,要求以nums中所有数组成的所有组合(每个组合中每个位置上的数能且只能被使用一次),且不能有重复的组合。例子:

思路:

回溯法。

与前一题不同的是本题数组中含有重复元素 ,需要剔除重复的组合。为了剔除重复的组合,需要对nums进行排序。

首先,组合选用某一个数的大前提肯定是该元素还未被访问。

其次,为了剔除重复,还得满足以下三个条件之一:

(1) 当前元素是第一个元素

(2) 当前元素不是第一个元素,但它与前一个元素不同

(3) 当前元素不是第一个元素,且它与前一个元素相同,但前一个元素已被访问

即若两个元素一样,则必须先访问了前面一个元素,才能访问后面相同的元素(否则的话,会产生重复的组合)

代码:

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (nums.length == 0)
            return res;
        Arrays.sort(nums); // 排序,更利于去重
        boolean[] visited = new boolean[nums.length]; // 用于记录各个位置的元素是否已被访问
        dfs(nums, new LinkedList<Integer>(), res, visited);
        return res;
    }
    public void dfs(int nums[], LinkedList<Integer> list, List<List<Integer>> res, boolean[] visited) {
        if (list.size() == nums.length) {
            res.add(new ArrayList<>(list));
            return ;
        }
        for (int i = 0; i < nums.length; i++) {
            /* 首先,要访问该元素,该元素肯定必须得是未被访问的,即 !visited[i]
                基于之上的条件,还需满足以下条件之一:
                1. 当前元素是第一个元素
                2. 当前元素不是第一个元素,但它与前一个元素不同
                3. 当前元素不是第一个元素,且它与前一个元素相同,但前一个元素已被访问
                即若两个元素一样,则必须先访问了前面一个元素,才能访问后面相同的元素(否则的话,会产生重复的组合)
            */
            if (!visited[i] && (i == 0 || nums[i] != nums[i - 1] || visited[i - 1])) {
                visited[i] = true;
                list.addLast(nums[i]);
                dfs(nums, list, res, visited);
                visited[i] = false;
                list.removeLast();
            }
        }
    }
}

结果:

结论:

总体思想和前一题类似,主要就是判断是否选该元素的条件有了更严格的限制。 

 

猜你喜欢

转载自blog.csdn.net/smart_ferry/article/details/88817584