码迷,mamicode.com
首页 > 其他好文 > 详细

【回溯】B001_LC_第k个排列(暴搜 / 数学剪枝)

时间:2020-09-17 15:38:42      阅读:16      评论:0      收藏:0      [点我收藏+]

标签:lse   顺序   输入   元素   else   math   接下来   情况   void   

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

"123"
"132"
"213"
"231"
"312"
"321"

给定 n 和 k,返回第 k 个排列。

说明:

给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。

示例 1:
输入: n = 3, k = 3
输出: "213"

示例 2:
输入: n = 4, k = 9
输出: "2314"

方法一:暴搜

思路

利用位掩码来记录数字的选择状态

class Solution {
public:
    string ans;
    int vis[10];
    void dfs(string& cur, int mask, int n, int& k) {
        if (cur.size() == n) {
            k--;
            if (!k) ans=cur;
            return;
        }
        for (int j=1; j<=n; j++) if ((mask & (1 << j-1)) == 0) {
            cur += to_string(j);
            dfs(cur, mask | (1<<j-1), n, k);
            cur.pop_back();
            if (!k) return;
        }
    }
    string getPermutation(int n, int k) {
        string cur="";
        memset(vis, 0, sizeof vis);
        dfs(cur, 0, n, k);
        return ans;
    }
};

复杂度分析

  • 时间复杂度:\(O(n!)\)
  • 空间复杂度:\(O(k)\)

方法二:数学剪枝

比如 n=4,k=9 时:

  • 假设第一位选择 1,则后面由 2、3、4 组成的排列共 3! 种,9 > 6 故 1 不可取
  • cur = "2",假设第一位选择 2,则后面由 1、3、4 组成的排列共 3! 种,但经过上面一层的过滤,此时剩下排列只有 9-6=3 种,而 3! > 3,故,k=9 时的全排列一定在以 2 为开头的排列中(k=3)
    • cur = "21" 由于 1 没有选,接下来如果选 1 的话,后面的 3、4 可以组成的排列则有 2! 个,但 \(3-2 > 1\) 故,1 也不可选,这里继续删除以 "21" 为开头的两个排列 "2134"、"2143"(k=1)
      • cur = "213" ,由于 3 没有选,接下来如果选 3 的话,此时只剩下的 4 组成的排列有 1 种,而 1-1 = 0,也就是 k=0 啦

注:假设从 n+1 层回退到上一层 n 的时候,由于第 n 层的选择是无效的,所以 vis 数组对 n+1 层选择的数字不会做出撤销

class Solution {
public:
    string s;
    int n,st[10],fac[10];
    void dfs(int& k) {
        if(s.size()==n){
            return; 
        }
        int c=fac[n-s.size()-1];
        for (int j=1; j<=n; j++) if (!st[j]) {
            if (k>c) {
                k-=c;
            } else {
                st[j]=1, s+=to_string(j);
                dfs(k);
            }
        }
    }
    string getPermutation(int n, int k) {
        fac[0]=1;
        for (int i=1; i<=n; i++) fac[i]=fac[i-1]*i;
        this->n=n;
        dfs(k);
        return s;
    }
};

复杂度分析

  • 时间复杂度:\(O(k)\)
  • 空间复杂度:\(O(n)\)

【回溯】B001_LC_第k个排列(暴搜 / 数学剪枝)

标签:lse   顺序   输入   元素   else   math   接下来   情况   void   

原文地址:https://www.cnblogs.com/zerostart0/p/13619439.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!