回溯算法之-排列 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);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章