求余+求根得到每个位上的排列字符+next_permutation 60. 第k个排列

本文探讨了在给定n和k的情况下,如何找到集合[1,2,...,n]的第k个排列。通过分析阶乘关系和迭代计算,提出了一种高效算法,避免了全排列的穷举,适用于n在1到9之间的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题

next_permutation 硬求,时间空间都很慢;
尝试通过n和k直接求出下一个排序;

当第一个数为1时,后面n-1个数有n-1!种排序方法,若k大于n-1!,则第一个数取2;
由此可得,k/(n-1!)的值为第一个数要取的数的下标;
取出后再原本的从1到n的列表中删除取出的数,用string储存的话可以用erase删除;
k=k%(n-1!),为剩下的数要解决的排序数量;

接下来剩下n-1个数,确定第二个数,通过k/(n-2!)找到新加入的数的下标;

终止条件
当只剩2个数时,k%1一定为0,所以余数为0为终止条件,最后把剩余的一个数加入结果即可;;
若前面还剩多个数时,k%n-1!为0,则这次添加完后,后续按原先顺序添加即可;

class Solution {
public:
    string getPermutation(int n, int k) {
        string s = "";
        for(int i=1;i<=n;i++) s+=to_string(i);
        string res="";
        --k;
        while(k>0)
        {
            int i =k/f(n-1);  //存放除数
            res+=s[i];
            s.erase(s.begin()+i); 
            k %=f(n-1);
            --n;               //n=2的时候,还剩下2个数,k%1必等于0了
        }
        return res+s;
    }
private:
    int f(int n)    //求阶乘
    {
        int sum=1;
        for(int i=2;i<=n;i++) sum*=i;
        return sum;
    }
};

next_permutation

class Solution {
public:
    string getPermutation(int n, int k) {
        string s = string("123456789").substr(0,n);
        for(int j = 1; j < k; ++j) next_permutation(s.begin(), s.end()); //罪过 罪过, 谢罪!
        return s;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值