46.全排列

46.全排列

题目

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:
输入:nums = [1]
输出:[[1]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

分析之后发现这道题还是在枚举所有的可能性,那么准备采用回溯法。

抽象树中,可以看出排列中[1,2]和[2,1]是两种不同的选择,而在组合中是一样。那就不需要使用startIndex来控制。组合问题其实取数有一规律都是从前往后选,但是排序不一样的,那么在取值的时候就需要判断之前的数是否被选了。

image

递归的参数和返回值

nums:输入的数组
path:存放单次排序的路径

List<List<Integer>> res = new ArrayList<>();
void backtracing(int[] nums,List<Integer> path);

递归的终止条件

递归的层数是确定的,只要所有的数都排列了就结束了

if(path.size() == nums.length){
	res.add(path);
	return;
}

递归的单层逻辑

每一次取值都需要从头到尾选择,不能取已经取过的值,那怎么表示值已经取过了?path的路径之中有就说明已经取值了,没有就说明还没有取过值

还可以设置一个visited数组记录元素是否被访问过。

for(int i =0;i<nums.length;i++){
   if(path.cantains(i))continue; //表示已经取过了,那就不能去跳到下一个
   path.add(i);
   backtracing(nums,path);
   path.remove(path.size()-1);
}

代码

class Solution {
    List<List<Integer>> res ;
    public List<List<Integer>> permute(int[] nums) {
        res = new ArrayList<>();
        backtracing(nums,new ArrayList<>());
        return res;
    }
    void backtracing(int[] nums,List<Integer> path){
        if(path.size() == nums.length){
	        res.add(new ArrayList(path));
        	return;
        }
        for(int num:nums){
            if(path.contains(num))continue;
            path.add(num);
            backtracing(nums,path);
            path.remove(path.size()-1);
        }
    }
}
posted @ 2021-06-19 11:14  rananie  阅读(70)  评论(0编辑  收藏  举报