[3]第k个排列

问题链接:
https://leetcode-cn.com/problems/permutation-sequence/
部分参考于:
https://leetcode-cn.com/problems/permutation-sequence/solution/di-kge-pai-lie-by-leetcode-solution/

算法

数学

注意到问题规模,如果将全排列全部列出,那么时间复杂度将为O(n!),那么最好是直接确定第k个排列。
由于排列的顺序是字典序排列的,那么根据k的范围就可以确定第一个数字的大小。即等于(k-1)/(n-1)!+1,此处为整数除法。

递归

可以转化为,先确定第一个数字,然后确定剩余排列的第一个元素,以此递归。

函数

string to_string(int val) ,仍旧是简单将int转化为string的函数。

实现

class Solution {
    
    
public:
    string getPermutation(int n,int k) {
    
    
        vector<int> factorial(n);
        factorial[0] = 1;
        for (int i = 1; i < n; ++i) {
    
    
            factorial[i] = factorial[i - 1] * i;//计算阶乘
        }
        --k;
        string ans;
        vector<int> valid(n + 1, 1);//状态数组
        for (int i = 1; i <= n; ++i) {
    
    
            int order = k / factorial[n - i] + 1;//向下取整
            for (int j = 1; j <= n; ++j) {
    
    
                order -= valid[j];//逼近下一个排列的开头,若为0则代表是已经使用过的,则order直接+0无影响order的值跳过
                if (!order) {
    
    //此时order恰好找到开头的数字
                    ans +=to_string(j);//string扩展
                    valid[j] = 0;//标记为已经使用的数字
                    break;//本轮查找结束,跳出循环,进入下一层
                }
            }
            k %= factorial[n - i];//k取得余数
        }   
        return ans;     
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_47741017/article/details/108418412