LeetCode第四十七题(全排列II)

107 阅读1分钟

回溯法

核心思想: 与LeetCode第四十六题的核心思想一致,只是需要增加去重操作,去重的方式为:先对数组nums[]进行排序,使得nums[]中的相同元素在相邻位置,并规定相同元素只能从左到右逐个填入空格即可。

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> resList = new ArrayList<>();//结果集
        List<Integer> res = new ArrayList<>();//排列组合
        int count = 0;//已填数字的空格个数,count=nums.length表示空格已填满
        boolean[] used = new boolean[nums.length];//标记数组,用于标记数组nums[]中的数字是否已使用
        Arrays.sort(nums);//对数组nums[]进行排序
        getResultListUnique(nums, resList, res, count, used);//回溯法求所有的排列组合
        return resList;
    }
    //回溯法求所有的排列组合
    void getResultListUnique(int[] nums, List<List<Integer>> resList, List<Integer> res, int count, boolean[] used){
        if(count == nums.length){//空格已填满
            resList.add(new ArrayList<>(res));//注意:先对res当前的内容进行拷贝,再加入结果集(因为res一开始为空,其内容在回溯过程一直改变,最后也为空)
            return;
        }
        for(int i = 0; i < nums.length; i++){//寻找数组nums[]中尚未使用过的数字
            if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {//去重操作
                continue;
            }
            res.add(nums[i]);//构建排列组合
            used[i] = true;//已使用
            getResultListUnique(nums, resList, res, count + 1, used);//递归构建排列组合
            res.remove(res.size() - 1);//撤销空格填入的数字
            used[i] = false;//撤销标记数组used[]的对应标记
        }
    }
}