leetcode 60 第k个排列

### 题目

给出集合 [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"


### 思路

        可以不用回溯法,直接通过要确定第几个排列,从而确定每个位置的元素。

我们知道N个元素一共有n!种排列,那么第n个数的每个不同的开头都有(n-1)!种排列,那么就可以可以对k做(n-1)!的除法得到第1个位置的数字应该是多少,然后再将k减去t*(n-1)!在开始循环,其中t就是k对(n-1)!做除法得到的商,具体通过一个例子来讲解:

假设 n=5,k=32,建立num矩阵[1,2,3,4,5].结果为res=“”;

通过计算得到(n-1)!=24,那么k除以24得到的是一个大于1小于2的数(这里不能直接用两个int相除,因为我们要判断是否这个除数时大于某个整数m的,因为等于m的时候取m-1,大于m小于m+1的时候取值时m),那么将t取值为1,取num[t]作为第一位的数,res=2,在num中删除掉num[t],num变为[1,3,4,5],k=k-t*24=8.

(n-2)!=6,8/6大于1小于2,所以t取1,第二位的数为num[t],删除num[t],num=[1,4,5],然后res=23,k=k-6=2;

(n-3)!=2,2/2等于1,所以t取0,第3位的数为num[t],删除num[t],num=[4,5],然后res=231,k=k-2*0=2;

(n-4)!=1,2/1等于2,所以t取1,第4位的数为num[t],删除num[t],num=[4],然后res=2315,k=k-1*1=1;

(n-5)!=1,1/1等于1,所以t取0,第5位的数为num[t],删除num[t],num=[],然后res=23154,k=k-1*1=0;

循环次数达到n的长度,循环结束,输出结果23154。

 

### code

class Solution {
public:
int jc(int n)
{
    int num=1;
    for(int i=1;i<=n;++i)
            num=num*i;
    return num;
}
    string getPermutation(int n, int k) {
        vector<string> num={"1","2","3","4","5","6","7","8","9"};
        if(n<=1)
            return "1";
        string res;
        for(int i=1;i<=n;++i)
        {
            int temp=jc(n-i);
            
            int l=ceil(double(k)/double(temp))-1;
            k=k-l*temp;
            res=res+num[l];
             num.erase (num.begin()+l);
        }
        return res;
        

    }
};


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值