Permutation Sequence

一. Permutation Sequence

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,

We get the following sequence (ie, for n = 3):

“123”
“132”
“213”
“231”
“312”
“321”

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

Difficulty:Medium

TIME:TIMEOUT

解法

这道题其实很有意思,之前做过Next Permutation,我也尝试用那种方法解这道题,结果会超时,而且并没有找到一种有序的递归解法(深度优先搜索在 9! 的时间复杂度下应该不会超时)。

不过,这道题既然是求第k个排列,那么我们其实毫不关心前面的k-1个排列究竟是怎样的

  • 如果给定序列<1,2,3>,那么可以把<1,2,3>的排列分解为三种子排列分别为<1,x,x>,<2,x,x>,<3,x,x>,其中x为剩下的两个数字中的一个。我们知道每个子排列的排列总数为 2!=2 ,因此子排列的序号范围便为1~2,3~4,5~6。
  • 然后,开始考虑序号和第一个数字之间的关联,如果都减一变为0~1,2~3,4~5(这里减一是正确的,加一反而不能处理很多情况),然后除以2,那么就为0,1,2,都加一变成1,2,3,这个数字就是第一个数字(这里的1,2,3并不是指1,2,3数字本身,而是指第1,2,3大的数字)。
  • 既然找到了第一个数字,那么我们减去第一个数字带来的影响,那么就可以开始考虑剩下的数字了,这个时候又回到了最开始的处理方法。

比如以<1,2,3>为例,我们要找第四个排列,步骤如下:

  • (41)/2=1 ,然后 1+1=2 ,第一个数字就是第二大的数子,这里为2,接着减去第一个数字带来的影响, 421=2
  • (21)/1=1 ,然后 1+1=2 ,第二个数字也是第二大的数字,这里为3,接着减去第二个数字带来的影响, 211=1
  • ….
  • 最后结果为<2,3,1>
string getPermutation(int n, int k) {
    string s;
    vector<int> v(n + 1, 1);
    vector<char> ch(n, '0');
    for(int i = 1; i <= n; i++) {
        v[i] = i * v[i - 1];
        ch[i - 1] += i;
    }
    while(n) {
        int num = (k - 1) / v[n - 1]; //这里判断需要第几大的数字
        k -= v[n - 1] * num; //减去这个数字带来的影响
        s.push_back(ch[num]);
        ch.erase(ch.begin() + num); //删掉该数字
        n--;
    }
    return s;
}

代码的时间复杂度为 O(n2)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值