LeetCode第四十六题(全排列)

135 阅读1分钟

回溯法

核心思想: 将数组nums[]中的数字填入nums.length个空格中,每个数字只能使用一次(可用数组used[]标记数组nums[]中的数字是否已使用),空格填满即可得一个排列组合,放入结果集resList中。

注意: 回溯的时候要撤销空格填入的数字以及标记数组used[]的对应标记,并继续尝试其他没被标记过的数字

class Solution {
    public List<List<Integer>> permute(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[]中的数字是否已使用
        getResultList(nums, resList, res, count, used);//回溯法求所有的排列组合
        return resList;
    }
    //回溯法求所有的排列组合
    void getResultList(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]){//尚未使用
                res.add(nums[i]);//构建排列组合
                used[i] = true;//已使用
                getResultList(nums, resList, res, count + 1, used);//递归构建排列组合
                res.remove(res.size() - 1);//撤销空格填入的数字
                used[i] = false;//撤销标记数组used[]的对应标记
            }
        }
    }
}