回溯算法之-排列 leetcode 46 全排列 Leetcode 47 全排列2

回溯算法之-组合总和请看:https://www.jianshu.com/p/2a9856b96a86

leetcode 46 全排列

给定一个 没有重复数字的序列,返回其所有可能的全排列。

先来说下排列和组合的区别,排列是给定可选择数组中每个数字都需要被使用;而组合则是根据题目要求可选择数组中数字的任意组合,并不是每个数字都需要,也并不是每个数字都需要使用。

还是套用https://www.jianshu.com/p/2a9856b96a86
一文中的回溯算法模板

public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
                // 排序非必须
        Arrays.sort(nums);
                // 判断数组中元素是否被使用,这里也可以使用HashSet来判断(因为题干中提示无重复数字)
        int[] used = new int[nums.length];
        help(res, nums, new ArrayList<Integer>(), used);
        return res;
    }

    private void help(List<List<Integer>> res, int[] nums, ArrayList<Integer> list, int[] used) {
                // 当集合元素=数组元素个数时,即代表这是一个全排列
        if (list.size() == nums.length) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            // 如果该元素已经被使用过了,跳过该元素
                        if (used[i] == 1) {
                continue;
            }
                        // 标识该元素已经被使用
            used[i] = 1;
            list.add(nums[I]);
            help(res, nums, list, used);
                        // 回溯过后将该元素置为未使用
            used[i] = 0;
        list.remove(list.size()-1);
        }
    }

Leetcode 47 全排列2

与46题相比,区别在于给定数字包含重复元素
套模板

public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
                // 排序非必须
        Arrays.sort(nums);
                // 判断数组中元素是否被使用,这里也可以使用HashSet来判断(因为题干中提示无重复数字)
        int[] used = new int[nums.length];
        help(res, nums, new ArrayList<Integer>(), used);
        return res;
    }

    private void help(List<List<Integer>> res, int[] nums, ArrayList<Integer> list, int[] used) {
                // 当集合元素=数组元素个数时,即代表这是一个全排列
        if (list.size() == nums.length) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            // 如果该元素已经被使用过了,跳过该元素
                        if (used[i] == 1) {
                continue;
            }
                        // 这里是与上一题唯一不同的地方,需要进行去重,如果当前数字和前一个数字相等,并且前一个数字是已经回溯过的,则代表他们是树结构的同一层,则进行跳过
            if(i>0 && nums[i] == nums[i-1] && (used[i-1]==0)){
                continue;
            }
                        // 标识该元素已经被使用
            used[i] = 1;
            list.add(nums[I]);
            help(res, nums, list, used);
                        // 回溯过后将该元素置为未使用
            used[i] = 0;
        list.remove(list.size()-1);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章