编程训练第十一期——全排列

编程问题:

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


示例:

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

解法:

1.回溯

  • 时间复杂度:O(N×N!),其中 N 为序列的长度。算法的复杂度首先受 backtrack 的调用次数制约,backtrack 的调用次数为 ∑ k = 0 N P ( N , k ) \sum_{k=0}^N {P\left(N,k\right)} k=0NP(N,k)次,其中 P ( N , k ) = N ! ( N − k ) ! = N ( N − 1 ) . . . ( N − k + 1 ) {P\left(N,k\right)} = \frac{N!}{(N-k)!} =N(N-1)...(N-k+1) P(N,k)=(Nk)!N!=N(N1)...(Nk+1),该式被称作 n 的 k - 排列,或者部分排列。 ∑ k = 0 N P ( N , k ) = N ! ( N − k ) ! = N ! + N ! 1 ! + N ! 2 ! + N ! 3 ! + . . . + N ! ( N − 1 ) ! < 2 N ! + N ! 2 + N ! 2 2 + . . . + N ! 2 n − 2 < 3 N ! \sum_{k=0}^N {P\left(N,k\right)} = \frac{N!}{(N-k)!} =N!+\frac{N!}{1!}+\frac{N!}{2!}+\frac{N!}{3!}+...+\frac{N!}{(N-1)!}<2N!+\frac{N!}{2}+\frac{N!}{2^2}+...+\frac{N!}{2^{n-2}}<3N! k=0NP(N,k)=(Nk)!N!=N!+1!N!+2!N!+3!N!+...+(N1)!N!<2N!+2N!+22N!+...+2n2N!<3N!,这说明 backtrack 的调用次数是 O(N!) 的。而对于 backtrack 调用的每个叶结点(共 N! 个),我们需要将当前答案使用 O(N) 的时间复制到结果数组中,相乘得时间复杂度为 O(N×N!)。因此时间复杂度为 O(N×N!)。
  • 空间复杂度:O(N),其中 N 为序列的长度。除结果数组以外,递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,这里可知递归调用深度为 O(N)。
class Solution {
private:
    void backTrack(vector<int>& nums, int n, vector<bool>& status, vector<vector<int>>& res, vector<int>& track) 
    {
        if (track.size() == n) 
        {
            res.push_back(track);
            return;
        }
        for (int i = 0; i < n; i++) 
        {
            if (!status[i])           //false 则可以填入结果数组
            {
                status[i] = true;
                track.push_back(nums[i]);
                backTrack(nums, n, status, res, track);
                track.pop_back();
                status[i] = false;   
            }
        }
    }
public:
    vector<vector<int>> permute(vector<int> &nums) 
    {
        vector<bool> status; //标记数组中已经填过的数
        vector<vector<int>> res;
        vector<int> track; //存放数字排列的结果数组
        int n = nums.size();
        status.resize(n, false);
        backTrack(nums, n, status, res, track);

        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值