60. 第k个排列

leetcode60:60. 第k个排列

题目描述

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

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

  1. “123”

  2. “132”

  3. “213”

  4. “231”

  5. “312”

  6. “321”

    给定nk,返回第k个排列。

    说明:

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

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

Example

输入:n = 3, k = 3
输出:"213"

solution idea

next_permutation 内置字符串函数

``C++ STL中提供了std::next_permutationstd::prev_permutation可以获取数字或者是字符的全排列,其中std::next_permutation提供升序、std::prev_permutation`提供降序。

class Solution {
/*
** next_permutation 内置字符串函数
*/
public:
    string getPermutation(int n, int k) {
        string s=string("123456789").substr(0,n);
        for(int i=1; i<k; i++) next_permutation(s.begin(),s.end());
        return s;
    }
};
根据规律直接查找第k个排列

考虑到我们的目标仅仅是找到第k个排列,有没有办法不用列举中间的排列,直接根据输入信息和排列规律直接找到第k个排列?在n个数字的排列中,根据手动排列的习惯,先固定第一个位置的数字,还剩下最多(n-1)!种排列,再由放到第一个位置的数字原先的位置i(从左往右第i个)的不同,表示跳过了 i ( n − 1 ) i(n-1) i(n1)种排列。

  • 要找到第k个排列,先由i = k/(n-1)得出应该移到第一个位置的数字索引;

  • 并由k = k%(n - 1)更新k;

  • 这样,我们可以从左往右遍历原先字符串的最小排列,每一次找到应该放在左边第一个位置的数字,将其添加到结果字符串中,并从原字符串中删除,然后对剩下的字符串重复这一操作,直到k==0

  • 此外由于字符串最初的状态就是第1个排列,所以要将输入的k先减一。

class Solution {
public:
/*
** 根据规律直接找第k个排列
*/
    int frac(int k) // k 阶乘
    {
        int res=1;
        while(k)
        {
            res*=k;
            k--;
        }
        return res;
    }
    string getPermutation(int n, int k) {
        string s=string("123456789").substr(0,n);
        string res;
        --k;
        int i;
        while(k)
        {
            int fra=frac(n-1);
            i=k/fra;
            res.push_back(s[i]);
            s.erase(s.begin()+i);
            k=k%fra;
            n--;
        }
        return res+s;
    }
};

参考文献

  1. c++ prime 第5版
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值