递归与回溯13:排列问题,全排列

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与回溯13:排列问题,全排列相关的知识,希望对你有一定的参考价值。

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

输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

排列问题是典型的小学生都会,但是难道众人的问题。如果自己写结果,很容易,但是如果要用计算机来做,就难多了。

这个问题与前面组合等问题的一个区别是使用过的后面还要再用,例如1,在开始使用了,但是到了2 和3的时候仍然要再使用一次。这本质上是因为 [1,2] 和 [2,1] 从集合的角度看是一个,但从排列的角度看是两个。

元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次,所以就不能使用startIndex了,需要一个used数组来标记已经选择的元素,完整过程如图所示:

这里的终止条件怎么判断呢?从上图可以看出叶子节点就是结果。那什么时候是到达叶子节点呢?

当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。

class Solution 

    List<List<Integer>> result = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) 
        if (nums.length == 0)
            return result;
        
        used = new boolean[nums.length];
        permuteHelper(nums);
        return result;
    

    private void permuteHelper(int[] nums)
        if (path.size() == nums.length)
            result.add(new ArrayList<>(path));
            return;
        
        for (int i = 0; i < nums.length; i++)
            if (used[i])
                continue;
            
            used[i] = true;
            path.add(nums[i]);
            permuteHelper(nums);
            path.removeLast();
            used[i] = false;
        
    

以上是关于递归与回溯13:排列问题,全排列的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 31:递归回溯八皇后全排列一篇文章全讲清楚

高频面试题LeetCode 31:递归回溯八皇后全排列一篇文章全讲清楚

求全排列(数组有重复元素和数组无重复元素) 回溯 递归

leetcode 46. Permutations 全排列(中等)

回溯算法01------全排列 + N皇后问题

leetcode 47. 全排列 II---回溯篇6