【Leetcode】46. 全排列

98 阅读2分钟

题目描述

在这里插入图片描述

// 46. 全排列

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

题解

// 回溯搜索
//
// 跟【Leetcode】39. 组合总和 很像,但又不一样,这里的排列组合需要反复用到nums中各个位置
// 的元素,所以我们不需要设定回溯搜索的起始位来限制搜索范围,
// 相反我们不限制搜索范围,每一次搜索都要扫描一遍nums中的元素。
// 但同时排列组合不能重复使用元素,因此我们设定一个元素使用标记boolean[] used,
// used与nums同大小,如果nums中i索引位元素被使用,则used中i索引位布尔值为true,
// 没被使用则为false。其他地方就跟39很像了,定义答案保存位res,
// 定义组合数组combination,当combination存满了就存入res。
// 
// 定义回溯搜索函数backtracking,老样子,先规定递归的终止条件,
// 如果combination已经存满了(size()等于nums长度),则将combination存入res中,
// 然后返回。
// for循环从头到尾遍历nums中的元素记为nums[i],如果used[i]位的boolean为true,
// 表示nums[i]已经被使用,continue跳过nums[i]这个数。
// 否则,则将nums[i]存入combination中,令used中的i索引位标记为true,
// 然后递归调用backtracking继续回溯搜索下一个元素。
// 当递归返回之后我们删除刚刚存入的nums[i],将used的i位重新置为false。
// 
// 执行用时:1 ms, 在所有 Java 提交中击败了96.72%的用户
// 内存消耗:38.6 MB, 在所有 Java 提交中击败了70.52%的用户
class Solution {
    public List<List<Integer>> permute(int[] nums) {
		boolean[] used = new boolean[nums.length];
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> combination = new ArrayList<>();
        backtracking(nums, res, combination, used);
        return res;
    }

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