递归——LeetCode47. Permutation II

来源:互联网 发布:散粉哪个比较好知乎 编辑:程序博客网 时间:2024/06/05 10:57

题目:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].


分析:

LeetCode47 与 LeetCode46 的区别就是提供的数字 nums[] 有重复,但是最后的排列方式不能有重复。

比如 nums = [1,1,2],如果按照LeetCode46的程序,结果为[1,1,2], [1,2,1], [1,1,2], [1,2,1], [2,1,1], [2,1,1],显然是不符合要求的。

如果对最后一步的results进行去重,逻辑是上可以的,但是已经得到了很多组没有用的结果,在LeetCode上也会因为Time Limit Exceed而不能通过。

所以LeetCode46在LeetCode47的递归基础上,需要使用一种重要的编程技巧:剪枝,即在递归过程中尽量省去没有必要的步骤。


代码:

public class LeetCode47 {    public static void main(String[] args) {        int[] nums = {1, 1, 2};        System.out.println(permuteUnique(nums));    }    public static List<List<Integer>> permuteUnique(int[] nums) {        Arrays.sort(nums);        List<List<Integer>> results = new ArrayList<List<Integer>>();        permuteUnique(results, new ArrayList<Integer>(), nums, new boolean[nums.length]);        return results;    }    private static void permuteUnique(List<List<Integer>> results, List<Integer> cur, int[] nums, boolean[] visited) {        if (cur.size() == nums.length) {            results.add(new ArrayList<Integer>(cur));            return;        }        for (int i = 0; i < nums.length; i++) {            if (visited[i] || i > 0 && nums[i] == nums[i-1] && !visited[i-1])                continue;            cur.add(nums[i]);            visited[i] = true;            permuteUnique(results, cur, nums, visited);            cur.remove(cur.size()-1);            visited[i] = false;        }    }}

if (visited[i] || i >0 &&  nums[i] == nums[i-1] && !visited[i-1])

visited[i]:如果该数已经被选过,则直接跳过该数,相当于LeetCode46中的条件判断cur.contains(nums[i])。由于LeetCode47中有重复的数字,所以不能通过cur.contains(nums[i])判断结果中是否有这个数值,只能判断该数是否被选过。

i > 0 && nums[i] == nums[i-1] && !visited[i-1]:对一个nums 中 index 大于0 的数,如果它和前面的一个数相等,前面的数字如果没被选,该数也不能被选;如果前面的数被选过了,该数可以考虑选。这样永远保证了相同数字只能按照nums中的顺序出现,就直接避免了 前1-后1 与 后1-前1 这类型的重复。


0 0
原创粉丝点击