一、不重复全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
https://leetcode.cn/problems/permutations/description/

1、dfs + boolean[]
通过boolean[]记录

    public List<List<Integer>> permute(int[] nums) {
        boolean[] used = new boolean[nums.length];
        return dfs(nums, used, new ArrayList<>(), new ArrayList<>());

    }

    private List<List<Integer>> dfs(int[] nums, boolean[] used, List<Integer> part, List<List<Integer>> ans) {
        if (part.size() == nums.length) {
            ans.add(new ArrayList<>(part));
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) {
                continue;
            }
            part.add(nums[i]);
            used[i] = true;
            dfs(nums, used, part, ans);
            part.remove(part.size() - 1);
            used[i] = false;
        }
        return ans;
    }

2、dfs + swap
较一快一丢丢丢,但是我觉得比一难理解很多

 public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        dfs(nums, 0, res);
        return res;
    }

    public void dfs(int[] nums, int index, List<List<Integer>> res) {
        if (index == nums.length) {
            ArrayList<Integer> list = new ArrayList<>();
            for (int num : nums) {
                list.add(num);
            }
            res.add(list);
            return res;
        }

        for (int i = index; i < nums.length; i++) {
            swap(nums, index, i);
            recursiveProgress(nums, index + 1, res);
            swap(nums, index, i);
        }
        return res;
    }

    public void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

二、重复全排列
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
https://leetcode.cn/problems/permutations-ii/description/

1、dfs + boolean[] + sort

    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        return backtrack(nums, new boolean[nums.length], 0, new ArrayList<>(), new ArrayList<>());
    }

    public List<List<Integer>> backtrack(int[] nums, boolean[] used, int idx, List<Integer> part, List<List<Integer>> ans) {
        if (idx == nums.length) {
            ans.add(new ArrayList<>(part));
            return ans;
        }
        for (int i = 0; i < nums.length; ++i) {
            if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])) {
                continue;
            }
            part.add(nums[i]);
            vis[i] = true;
            backtrack(nums, used, idx + 1, part, ans);
            vis[i] = false;
            part.remove(idx);
        }
        return ans;
    }

2、dfs + swap + flag

    public List<List<Integer>> permuteUnique(int[] nums) {
        return dfs(nums, 0, new ArrayList<>());
    }

    private List<List<Integer>> dfs(int[] nums, int idx, List<List<Integer>> ans) {
        if (idx == nums.length) {
            List<Integer> part = new ArrayList<>();
            for (int num : nums) {
                part.add(num);
            }
            ans.add(part);
        }
        for (int i = idx; i < nums.length; i++) {
            boolean flag = false;
            for (int j = idx; j < i; j++) {
                if (nums[j] == nums[i]) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                continue;
            }
            swap(nums, i, idx);
            dfs(nums, idx + 1, ans);
            swap(nums, i, idx);
        }
        return ans;
    }

三、排列计数
给定 n 和 k,返回第 k 个排列。
https://leetcode.cn/problems/permutation-sequence/description/

  public class Solution{  
    boolean[] used;
    int[] nums;
    int total = 0;
    int[] factor;

    public String getPermutation(int n, int k) {
        init(n, k);
        List<Integer> part = new ArrayList<>();
        find(0, n, k, part);
        return part.stream().map(e -> e.toString()).collect(Collectors.joining());
    }

    private void init(int n, int k) {
        factor = new int[n + 1];
        factor[0] = 1;
        for (int i = 1; i <= n; i++) {
            factor[i] = factor[i - 1] * i;
        }
        this.nums = IntStream.range(1, n + 1).toArray();
        this.used = new boolean[n];
    }

    private void find(int depth, int n, int k, List<Integer> part) {
        if (part.size() == nums.length) {
            ++total;
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            int cnt = factor[n - depth - 1];
            if (used[i]) {
                continue;
            }
            if (total + cnt < k) {
                total += cnt;
                continue;
            }
            part.add(nums[i]);
            used[i] = true;
            find(depth + 1, n, k, part);
            if (total == k) {
                return;
            }
            part.remove(part.size() - 1);
            used[i] = false;

        }
    }
}

lindsay_bubble
26 声望11 粉丝